-
Notifications
You must be signed in to change notification settings - Fork 20
Component
Creating components in Fleks requires a little bit of boilerplate code. To save the precious time of your life, I suggest to use a Live Template. In IntelliJ this is done via Setting -> Live Templates. I use e.g. the 'flekscomponent' abbreviation in the editor to auto generate the component code:
The Template text I am using is:
import com.github.quillraven.fleks.Component
import com.github.quillraven.fleks.ComponentType
class $FLEKS_COMPONENT$ : Component<$FLEKS_COMPONENT$> {
override fun type() = $FLEKS_COMPONENT$
companion object : ComponentType<$FLEKS_COMPONENT$>()
}
A component requires the implementation of the generic Component
interface which requires the implementation of a type
function that returns a ComponentType
.
A ComponentType
is simply assigning a unique ID per type of component (not per instance!) which is needed by Fleks internally to optimize the performance by knowing which index of certain arrays to access. In Kotlin we can simply extend the unnamed companion object with the ComponentType
abstract class. This allows for a fluent and intuitive API when working with entities and components. Here is an example of a position component:
data class Position(
var x: Float,
var y: Float,
) : Component<Position> {
override fun type(): ComponentType<Position> = Position
// this assigns the Position component a unique ID
companion object : ComponentType<Position>()
}
It is also possible to use the same component for different purposes. E.g. let's imagine we have a Sprite component and want to distinguish between a foreground and background sprite. By implementing a more advanced type
function we can achieve that. The example also illustrates the usage of componentTypeOf
which is a convenience function to create a ComponentType
:
data class Sprite(
val background: Boolean,
var path: String = "",
) : Component<Sprite> {
override fun type(): ComponentType<Sprite> {
return when (background) {
true -> SpriteBackground
else -> SpriteForeground
}
}
companion object {
val SpriteForeground = componentTypeOf<Sprite>()
val SpriteBackground = componentTypeOf<Sprite>()
}
}
Here are examples of some base functionalities you can do with components and entities in a Fleks context (=world, system, family and family hooks):
data class Position(
var x: Float,
var y: Float,
) : Component<Position> {
override fun type(): ComponentType<Position> = Position
companion object : ComponentType<Position>()
}
fun main() {
val world = configureWorld { }
// creating an entity with a position component
val entity = world.entity {
it += Position(3f, 4f)
}
// Start a Fleks context. This is only necessary if you are not within a system, family or hook.
with(world) {
// access and modify the position
entity[Position].x = 5f
// access in case you are not sure if an entity has a component or not
entity.getOrNull(Position)?.let { position ->
// ...
}
// Check if an entity has a position. There is also a 'hasNo' version.
if (entity has Position) {
// ...
}
// another way to check if a component is present
if (Position in entity) {
// ...
}
// modify an entity by removing its position component
entity.configure {
it -= Position
}
}
}