Utilities and type-safe builders for the Ashley entity component system.
Since Ashley contains many generic methods consuming Class instances, Kotlin can
provide a pleasant DSL via inlined methods reified generic types. Additionally, creating Entities and their respective
Components can result in a lot of declarative-style code which is greatly improved by an easily readable type-safe
builder DSL.
ktx-ashley provides the following extensions and utilities:
Engine.addandEngine.entityextension methods provide type-safe building DSL for creatingEntities.Engine.getSystemandEngine.get([]operator) ease access to registeredEntitySysteminstances of the engine.Engine.getSystemthrows aMissingEntitySystemExceptionin case the system is not part of theEngine.Engine.getreturnsnullin such cases.EngineEntityis anEntitywrapper that allows to createComponentinstances using using theEngineviawithmethod. It is available when callingEngine.entityorEngine.configureEntity.Engine.configureEntityextension method allows to add components to an existing entity.mapperForfactory method allows to createComponentMapperinstances.- Accessors for
Entityobjects usingComponentMappers:get([]operator),has,hasNot,contains(inoperator),remove. Entity.addComponentextension method allows to create and add a singleComponentto an existingEntity.Entity.plusAssign(+=) operator allows to add aComponentto an existingEntity.- Top-level and
Builderextension DSL methods for constructingFamilybuilders withKClassinstances:oneOf,allOf,exclude.
Creating a new pooled Entity:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
val engine = PooledEngine()
class Texture: Component
class Transform(var x: Float = 0f, var y: Float = 0f) : Component
val entity = engine.entity {
with<Texture>()
with<Transform> {
x = 1f
y = 1f
}
}Creating multiple new entities:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
val engine = PooledEngine()
class Transform(var x: Float = 0f, var y: Float = 0f) : Component
fun setupEngine() = engine.add {
entity {
with<Transform> {
x = 1f
y = 1f
}
}
entity {
with<Transform> {
x = 2f
y = 2f
}
}
}Adding new components to an existing entity with Engine.configureEntity:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.Entity
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
val engine = PooledEngine()
val entity = Entity()
class Transform(var x: Float = 0f, var y: Float = 0f) : Component
fun extendEntity(){
engine.configureEntity(entity) {
with<Transform> {
x = 1f
y = 1f
}
}
}Getting an EntitySystem from an Engine:
import com.badlogic.ashley.core.EntitySystem
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.get
import ktx.ashley.getSystem
class MoveSystem : EntitySystem()
class RenderSystem : EntitySystem()
val engine = PooledEngine()
fun getSystem() {
engine.addSystem(MoveSystem())
engine.addSystem(RenderSystem())
// Non-nullable variant - throws an exception if the system is missing:
val moveSystem = engine.getSystem<MoveSystem>()
// Nullable variant - returns null if the system is missing:
val renderSystem = engine[RenderSystem::class]
}Creating a ComponentMapper:
import com.badlogic.ashley.core.Component
import ktx.ashley.mapperFor
class Transform: Component
val transformMapper = mapperFor<Transform>()Adding a Component to an existing Entity:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.Engine
import com.badlogic.ashley.core.Entity
import ktx.ashley.addComponent
import ktx.ashley.plusAssign
class Transform(var x: Float = 0f, var y: Float = 0f) : Component
fun addComponentToEntity(entity: Entity, engine: Engine) {
// Creating and adding a component:
entity.addComponent<Transform>(engine) {
x = 2.5f
y = 5f
}
// Or alternatively, if you already have a constructed component:
entity += Transform(x = 1f, y = 2f)
}Getting a Component from an Entity:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
class Transform: Component
val engine = PooledEngine()
val transform = mapperFor<Transform>()
val entity = engine.entity {
with<Transform>()
}
val component: Transform = entity[transform]Checking if an Entity has a Component:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
class Transform: Component
val engine = PooledEngine()
val transform = mapperFor<Transform>()
val entity = engine.entity {
with<Transform>()
}
val hasTransform: Boolean = entity.has(transform)
// Or alternatively:
val containsTransform: Boolean = transform in entityRemoving a Component from an Entity:
import com.badlogic.ashley.core.Component
import com.badlogic.ashley.core.PooledEngine
import ktx.ashley.*
class Transform: Component
val engine = PooledEngine()
val entity = engine.entity {
with<Transform>()
}
fun removeTransform() {
entity.remove<Transform>()
}Creating a component Family that matches all entities with the selected Component types with an exclusion:
import com.badlogic.ashley.core.Component
import ktx.ashley.*
class Texture: Component
class Transform: Component
class RigidBody: Component
var family = allOf(Texture::class, Transform::class).exclude(RigidBody::class)