General utilities for handling libGDX graphics-related API.
While libGDX API is not particularly bad in this case and the KTX module provides only minor improvements, Kotlin build-in features can greatly simplify some common operations related to graphics and prevent some common bugs such as forgetting to start or end batch rendering.
use
inlined extension methods added toBatch
,ShaderProgram
andGLFrameBuffer
. They allow safe omission of thebegin()
andend()
calls when using batches, shader programs and buffers. Note that a camera or a matrix can also be passed to selected extension methods to have it automatically applied as the projection matrix.begin
extension methods that automatically set projection matrix from aCamera
orMatrix4
were added toBatch
.takeScreenshot
allows to easily take a screenshot of current application screen.BitmapFont.center
extension method allows calculating center position of text in order to draw it in the middle of a chosen object.
color
factory methods allows using named parameters to construct libGDXColor
instances.copy
extension method added toColor
. It allows to create a newColor
with copied color values. Supports overriding individual color values with optional named parameters.Color
instances can be destructed into individual color values.
ShapeRenderer
API, which normally consumes float
primitives, was extended to support Vector2
and Vector3
instances instead of x
, y
and z
position parameters. The extension methods have the same names as the
original ShapeRenderer
methods and perform the same actions. The methods include:
arc
box
circle
cone
ellipse
rect
rectLine
rotate
scale
translate
triange
A use
inlined extension method is also available for ShapeRenderer
, ensuring you won't have unbalanced begin()
and end()
calls.
Camera.center
extension method allows to center the camera's position to screen center or the center of the chosen rectangle.Camera.moveTo
extension method allows to move the camera immediately at the chosen target position with optional offset.Camera.lerpTo
extension method allows to move the camera smoothly to the chosen target position with optional offset.Camera.update
inlined extension method changes camera state with automaticCamera.update
call.LetterboxingViewport
combinesScreenViewport
andFitViewport
behavior: it targets a specific aspect ratio and applies letterboxing likeFitViewport
, but it does not scale rendered objects when resized, keeping them in fixed size similarly toScreenViewport
. Thanks to customizable target PPI value, it is ideal for GUIs and can easily support different screen sizes.
Using a Batch
:
import ktx.graphics.*
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.SpriteBatch
val batch = SpriteBatch()
val font = BitmapFont()
// Drawing the font with batch:
batch.use {
font.draw(it, "KTX!", 100f, 100f)
}
/* The snippet above is an equivalent to:
batch.begin()
font.draw(batch, "KTX!", 100f, 100f)
batch.end()
*/
Using a Batch
with a Camera
:
import ktx.graphics.*
import com.badlogic.gdx.graphics.OrthographicCamera
val camera = OrthographicCamera()
// Projection matrix will be copied from the camera:
batch.use(camera) {
font.draw(it, "KTX!", 100f, 100f)
}
/* Equivalent to:
batch.projectionMatrix = camera.combined
batch.begin()
font.draw(batch, "KTX!", 100f, 100f)
batch.end()
*/
Using a ShaderProgram
:
import ktx.graphics.*
shaderProgram.use {
// Operate on shaderProgram instance.
}
/* The snippet above is an equivalent to:
shaderProgram.begin()
// Operate on shaderProgram instance.
shaderProgram.end()
*/
Creating Color
instances:
import ktx.graphics.*
val myColor = color(red = 1f, green = 0.5f, blue = 0.75f, alpha = 0.25f)
// Fourth parameter - alpha - is optional and defaults to 1f:
val nonTransparentGray = color(0.8f, 0.8f, 0.8f)
Copying Color
instances:
import ktx.graphics.*
import com.badlogic.gdx.graphics.Color
val blue = Color.BLUE.copy()
// `blue` has same values as `Color.BLUE`, but it's not the same instance.
// You can optionally override chosen copied values:
val violet = blue.copy(red = 1f)
Destructing Color
instances:
import ktx.graphics.*
import com.badlogic.gdx.graphics.Color
fun destruct(color: Color) {
val (red, green, blue, alpha) = color
}
Using a ShapeRenderer
:
import ktx.graphics.*
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
val shapeRenderer = ShapeRenderer()
shapeRenderer.use(ShapeRenderer.ShapeType.Filled) {
// Operate on shapeRenderer instance
}
/* The snippet above is an equivalent to:
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled)
// Operate on shapeRenderer instance
shapeRenderer.end()
*/
Using a ShapeRenderer
with a Camera
:
import ktx.graphics.*
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
val camera = OrthographicCamera()
val shapeRenderer = ShapeRenderer()
// Projection matrix will be copied from the camera:
shapeRenderer.use(ShapeRenderer.ShapeType.Filled, camera) {
// Operate on shapeRenderer instance
}
/* Equivalent to:
shapeRenderer.projectionMatrix = camera.combined
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled)
// Operate on shapeRenderer instance
shapeRenderer.end()
*/
Using ShapeRenderer
with vectors:
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import com.badlogic.gdx.math.Vector2
import ktx.graphics.circle
fun drawCircle(renderer: ShapeRenderer) {
val position = Vector2(1f, 0f)
renderer.circle(position, radius=5f)
}
Taking a screenshot of the current game screen:
import com.badlogic.gdx.Gdx
import ktx.graphics.takeScreenshot
takeScreenshot(Gdx.files.external("mygame/screenshot.png"))
Finding out where to draw text in order to center it on a Sprite
:
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.Sprite
import com.badlogic.gdx.math.Vector2
import ktx.graphics.center
fun getCenterAtSprite(
bitmapFont: BitmapFont, text: String, sprite: Sprite
): Vector2 =
bitmapFont.center(
text,
// Note that x or y can be modified if you want a slight offset:
x = sprite.x, y = sprite.y,
width = sprite.width, height = sprite.height
)
Creating and customizing a new LetterboxingViewport
:
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.utils.viewport.Viewport
import ktx.graphics.LetterboxingViewport
class Application: ApplicationAdapter() {
val viewport: Viewport = LetterboxingViewport(targetPpiX = 96f, targetPpiY = 96f, aspectRatio = 4f / 3f)
override fun resize(width: Int, height: Int) {
// Updating viewport to the new screen size:
viewport.update(width, height, true)
}
}
Centering camera position:
import com.badlogic.gdx.graphics.OrthographicCamera
import ktx.graphics.center
fun centerCamera(camera: OrthographicCamera) {
// Sets position to the middle of the screen:
camera.center()
// Sets position to the middle of the chosen rectangle:
camera.center(x = 100f, y = 100f, width = 800f, height = 800f)
}
Moving the camera to a target:
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.math.Vector2
import ktx.graphics.lerpTo
import ktx.graphics.moveTo
fun moveCamera(camera: OrthographicCamera, target: Vector2) {
// Moves the camera immediately at the target:
camera.moveTo(target)
// Moves the camera smoothly to the target:
camera.lerpTo(target, lerp = 0.1f)
}
Changing the camera state with automatic update:
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.math.Vector2
import ktx.graphics.lerpTo
import ktx.graphics.update
fun moveCamera(camera: OrthographicCamera, target: Vector2) {
camera.update {
lerpTo(target, lerp = 0.1f)
// camera.update() will be called automatically after this block.
}
}
Use ktx-math
for Vector2
and Vector3
extensions, including idiomatic Kotlin factory
methods and operator overloads.
There are some general purpose libGDX utility libraries, but most lack first-class Kotlin support.