FlixelGDX KTX is a powerful, all-in-one Kotlin extension of the Java-based game framework FlixelGDX. If you like the simplicity of the framework's API, but want to use Kotlin-flavored syntax and features with it, this extension is the perfect one for you.
FlixelGDX KTX provides a multitude of tooling, including syntatic sugar, DSLs, out-of-the-box support for beloved Kotlin features like coroutines and property delegates, and so much more!
The extension provides a set of delegates that integrate nicely with the framework's API.
// Save data to disk automatically from easy-to-read properties.
class SettingsState : FlixelState() {
var masterVolume by save(1f) // Stored under the key "masterVolume".
var playerName by save("Hero") // Stored under the key "playerName".
override fun destroy() {
super.destroy()
Flixel.save.flush() // Persist the accumulated changes to disk once.
}
}Every FlixelGDX collection type gets clean, concise syntatic sugar to keep game development quick, easy and fun.
val steak = Steak()
val inventory = flixelArrayOf(Sword(), steak) // Create a new FlixelArray.
inventory += Potion() // Add a new object to the array.
inventory -= steak // Remove an object from the array.
val item = inventory[1] // Access an element by index.
val hasPotion = steak in inventory // Check if an element exists.
// Loop through a primitive array with an inlined, allocation-free forEach DSL.
val ids = flixelIntArrayOf(86749, 2844)
ids.forEach {
Flixel.info(it)
}
// Instantly create a pool with ease.
val bullets = flixelPool { Bullet() }The extension provides an extended tween(...) function for all objects, keeping code simple and readable.
// Slide a sprite to (500, 300) over 1.5 seconds with a bounce.
sprite.tween(duration = 1.5f, ease = FlixelEase::bounceOut) {
goal(sprite::getX, 500f, sprite::setX)
goal(sprite::getY, 300f, sprite::setY)
}
// Chain tweens together in a clean sequence.
button.tween(duration = 1f) {
goal(button::getX, 100f, button::setX)
}.then {
sprite.tween(duration = 2.5f) {
goal(sprite::getY, 0f, sprite::setY)
}
}FlixelGDX KTX provides clean, direct integration with the framework's core API and Kotlin's native coroutine system.
Coroutines are part of flixelgdx-ktx-core and are built only on the Kotlin standard library, so they work on every
platform, web builds included.
val onDialogClosed = FlixelSignal<Unit>()
override fun create() {
// Install the extension's coroutine system once in your game.
installFlixelCoroutines()
// Then use them anywhere in your game.
launch {
delay(1f) // Wait 1 real game-loop second.
introTween.await() // Wait until the tween finishes
onDialogClosed.awaitOnce() // Wait for the player to dismiss the dialog.
Flixel.switchState { PlayState() }
}
}If your game uses FlixelGDX UI, the flixelgdx-ktx-ui module lets the
shape of your code match the shape of your menus.
// Declare your looks once.
val skin = uiSkin {
button {
up = track(nineSlice(Flixel.files.internal("ui/button.png"), all = 6))
}
button("danger") {
up = track(colorFill(0xAA2222FF))
}
label("title") {
fontSize = 32
}
slider {
track = track(colorFill(0x333333FF))
thumb = track(colorFill(0xEEEEEEFF))
}
}
// Then build the UI as a tree. Each widget is added to the block it is written in.
ui = uiDisplay(FlixelUiDisplay.createHudCamera(), skin) {
vstack(spacing = 8f) {
anchor(FlixelAlign.CENTER)
label("Main Menu", style = "title")
button("Play", tooltip = "Start a new run") {
onClick {
startGame()
}
}
checkbox("Fullscreen").bind(settings::fullscreen) // Two-way binding, works with save().
dropdown(160f) {
items("Low", "Medium", "High")
}.bind(settings::quality)
hslider(200f, max = 100f, step = 5f).bind(settings::volume) // Use vslider(...) for a vertical one.
picture(Flixel.files.internal("ui/logo.png"), 128f, 64f, FlixelUiPicture.ScaleMode.FIT)
button("Quit", style = "danger") {
onClick {
confirmQuit()
}
}
}
}With coroutines, a dialog is just a function that returns the player's answer:
fun confirmQuit() = launch {
val quit = ui.dialog(300f, 160f, dismissed = false) { finish ->
label("Really quit?")
hstack(spacing = 8f) {
button("Yes") { onClick { finish(true) } }
button("No") { onClick { finish(false) } }
}
}
if (quit) Flixel.quit()
}Just like the UI extension itself, none of this reads input: your game still decides when a widget is hovered or
clicked (the UI extension's FlixelUiPointer makes that a few lines).
It's as easy as adding a few lines to your build script or configuration file.
[versions]
flixelgdx-ktx = "<flixelgdx-version>"
[libraries]
flixelgdx-ktx-core = { module = "org.flixelgdx:flixelgdx-ktx-core", version.ref = "flixelgdx-ktx" }
flixelgdx-ktx-ui = { module = "org.flixelgdx:flixelgdx-ktx-ui", version.ref = "flixelgdx-ktx" }// build.gradle.kts (in your core module of your game).
dependencies {
implementation(libs.flixelgdx.ktx.core)
implementation(libs.flixelgdx.ktx.ui) // If you use FlixelGDX UI.
}// In your root build.gradle.kts:
repositories {
mavenCentral()
}
// In your game's core build.gradle.kts script:
dependencies {
implementation("org.flixelgdx:flixelgdx-ktx-core:<flixelgdx-version>")
implementation("org.flixelgdx:flixelgdx-ktx-ui:<flixelgdx-version>") // If you use FlixelGDX UI.
}<dependency>
<groupId>org.flixelgdx</groupId>
<artifactId>flixelgdx-ktx-core</artifactId>
<version>FLIXELGDX-VERSION</version>
</dependency>
<!-- If you use FlixelGDX UI. -->
<dependency>
<groupId>org.flixelgdx</groupId>
<artifactId>flixelgdx-ktx-ui</artifactId>
<version>FLIXELGDX-VERSION</version>
</dependency>- Contributing Guide: Coding standards, PR requirements, and how to contribute.
- Project Structure: The multi-module layout and how Gradle is used.
- Compiling & Testing: How to build the framework and test it as a dependency in your own projects.
- Code of Conduct: Rules set in place for a stable open source community.
- Project Roles: How each role for the project operates, including project leaders and maintainers.