Skip to content

Latest commit

 

History

History

artemis

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Artemis-odb Maven Central

KTX: Artemis-odb ECS utilities

Utilities and type-safe builders for the Artemis-odb entity-component-system.

Why?

Artemis-odb does not target Kotlin out of the box. Kotlin can provide a highly readable DSL via inlined methods with 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.

Guide

ktx-artemis provides the following extensions and utilities:

  • ArchetypeBuilder.add adds components to an ArchetypeBuilder.
  • ArchetypeBuilder.remove removes component from an ArchetypeBuilder.
  • Aspect.Builder has extension functions to use KClass instances: oneOf, allOf, exclude.
  • oneOf, allOf, exclude are also available as standalone Aspect builder functions.
  • EntityEdit.plusAssign adds components to an entity with a += operator function.
  • EntityEdit.with adds or replaces a component of an entity.
  • EntityEdit.remove removes a component from the entity.
  • EntityTransmuterFactory.add adds a component to an EntityTransmuterFactory.
  • EntityTransmuterFactory.remove removes a component from an EntityTransmuterFactory.
  • ComponentMapper.contains checks if an entity has a component with the in operator function.
  • World.edit edits an entity by its id with a type-safe builder DSL.
  • World.entity creates and adds an entity to the world with a type-safe builder DSL.
  • World.get retrieves a system from the world with get ([] operator).
  • World.getSystem retrieves a system from the world with a type-safe builder DSL.
  • World.mapperFor retrieves a ComponentMapper instance.

Usage examples

Creating a new Entity:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.entity

val world = World()

class Texture : Component()
class Transform(var x: Float = 0f, var y: Float = 0f) : Component()

val entity = world.entity {
    with<Texture>()
    with<Transform> {
        x = 1f
        y = 1f
    }
}

Adding new components to an existing entity with World.edit:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.edit
import ktx.artemis.entity
import ktx.artemis.with

val world = World()

class Transform(var x: Float = 0f, var y: Float = 0f) : Component()

val entityId = world.entity()

fun editWorld() {
  world.edit(entityId) {
    with<Transform> {
      x = 1f
      y = 1f
    }
  }
}

Getting a BaseSystem from the World:

import com.artemis.*
import ktx.artemis.*

class MoveSystem : BaseSystem() {
  override fun processSystem() = Unit
}
class RenderSystem : BaseSystem() {
  override fun processSystem() = Unit
}

val world = World(
  WorldConfigurationBuilder()
    .with(MoveSystem(), RenderSystem())
    .build()
)

fun getSystem() {
  // Non-nullable variant - throws an exception if the system is missing:
  val moveSystem = world.getSystem<MoveSystem>()
  // Nullable variant - returns null if the system is missing:
  val renderSystem = world[RenderSystem::class]
}

Creating a ComponentMapper:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.mapperFor

class Transform : Component()

val world = World()
val transformMapper = world.mapperFor<Transform>()

Adding a Component to an existing Entity:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.*

class Transform(var x: Float = 0f, var y: Float = 0f) : Component()

fun addComponentToEntity(entityId: Int, world: World) {
  // Creating and adding a component:
  val entityEdit = world.edit(entityId) {
    with<Transform> {
      x = 2.5f
      y = 5f
    }
  }

  // Or you can add a component with the += operator:
  entityEdit += Transform(x = 1f, y = 2f)
}

Removing a Component from an Entity:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.*

class Transform : Component()

val world = World()
val entityId = world.entity {
  with<Transform>()
}

fun removeTransform() {
  world.edit(entityId).remove<Transform>()
}

Getting a Component from an Entity with a ComponentMapper:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.*

class Transform : Component()

val world = World()
val transformMapper = world.mapperFor<Transform>()
val entityId = world.entity {
  with<Transform>()
}
val transformComponent: Transform = transformMapper[entityId]

Checking if an Entity has a Component with a mapper:

import com.artemis.Component
import com.artemis.World
import ktx.artemis.*

class Transform : Component()

val world = World()
val transformMapper = world.mapperFor<Transform>()
val entityId = world.entity {
  with<Transform>()
}
val hasTransform: Boolean = entityId in transformMapper

Creating a component Aspect that matches all entities with the selected Component types with an exclusion:

import com.artemis.*
import com.artemis.systems.IteratingSystem
import ktx.artemis.*

class Texture : Component()
class Transform : Component()
class RigidBody : Component()

val world = World()
val aspectBuilder = allOf(Texture::class, Transform::class).exclude(RigidBody::class)

// The AspectBuilder can be added to a system for example
class ExampleIteratingSystem : IteratingSystem(aspectBuilder) {
  override fun process(entityId: Int) = Unit
}

Adding and removing components from an Archetype:

import com.artemis.ArchetypeBuilder
import com.artemis.Component
import ktx.artemis.*

class Texture : Component()
class Transform : Component()
class RigidBody : Component()

fun createArchetype() {
  val archetypeBuilder = ArchetypeBuilder()
    .add(Transform::class, Texture::class)

  // You can also add components one by one with generic type:
  archetypeBuilder.add<RigidBody>()

  // You can just as easily remove components:
  archetypeBuilder.remove<RigidBody>()
}

Adding and removing a component from an EntityTransmuterFactory:

import com.artemis.Component
import com.artemis.EntityTransmuterFactory
import com.artemis.World
import ktx.artemis.*

val world = World()

class Texture : Component()
class Transform : Component()

val transmuterFactory = EntityTransmuterFactory(world)
  .add<Transform>()
  .remove<Texture>()

Alternatives

  • Fleks is a high performance Kotlin ECS library. Written with a Kotlin DSL from day one, it does not require similar utilities to the Java ECS frameworks.
  • Ashley is a Java ECS library maintained the libGDX organization. KTX provides utilities for Ashley via the ktx-ashley module.

Additional documentation