Component - Quillraven/Fleks GitHub Wiki

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: image

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
        }
    }
}
⚠️ **GitHub.com Fallback** ⚠️