Home

Awesome

entitas-lua

Entitas ECS implementation in Lua.

entitas-lua is a port of Entitas ECS for C# and Unity

entitas-lua reference entitas-python

Run Test and Example

    ./lua test/test_entity_system.lua
    ./lua example/HelloWorld/Example.lua

Overview

Components

local MakeComponent = require('entitas.MakeComponent')
local Position = MakeComponent("Position", "x", "y", "z")
local Movable = MakeComponent("Movable", "speed")
local Person = MakeComponent("Person", "name","age")

Entity

    local entity = Entity.new()

    entity:activate(0)
    entity:add(Position, 1, 4, 5)
    assert(entity:has(Position))
    assert(entity:has_any({Position}))

    local pos = entity:get(Position)
    assert(pos.x == 1)
    assert(pos.y == 4)
    assert(pos.z == 5)

    entity:replace(Position, 5, 6)

    entity:replace(Person, "wang")

    assert(entity:get(Position).x == 5)
    assert(entity:get(Position).y == 6)

    entity:remove(Position)
    assert(not entity:has(Position))

    entity:add(Position, 1, 4, 5)
    entity:add(Movable, 0.56)
    assert(entity:has_all({Position, Movable}))
    entity:destroy()
    assert(not entity:has_all({Position, Movable}))

Context

    local _context = Context.new()
    local _entity = _context:create_entity()

    assert(Context.create_entity)
    assert(Context.has_entity)
    assert(Context.destroy_entity)
    assert(Context.get_group)
    assert(Context.set_unique_component)
    assert(Context.get_unique_component)

    assert(_context:has_entity(_entity))
    lu.assertEquals(_context:entity_size(), 1)
    _context:destroy_entity(_entity)
    assert(not _context:has_entity(_entity))

    -- reuse
    local _e2 = _context:create_entity()
    assert(_context:has_entity(_entity))
    lu.assertEquals(_context:entity_size(), 1)


    _context:set_unique_component(Counter,101)
    local cmp = _context:get_unique_component(Counter)
    assert(cmp.num == 101)

Group

    local _context = Context.new()
    local _entity = _context:create_entity()

    _entity:add(Movable, 1)

    local _group = _context:get_group(Matcher({Movable}))
    local _group2 = _context:get_group(Matcher({Movable}))
    assert(_group==_group2)

    assert(_group.entities:size() == 1)
    assert(_group:single_entity():has(Movable))

    assert(_group:single_entity() == _entity)
    _entity:replace(Movable, 2)
    assert(_group:single_entity() == _entity)
    _entity:remove(Movable)
    assert(not _group:single_entity())

    _entity:add(Movable, 3)

    local _entity2 = _context:create_entity()
    _entity2:add(Movable, 10)
    lu.assertEquals(_group.entities:size(), 2)
    local entities = _group.entities

    assert(entities:has(_entity))
    assert(entities:has(_entity2))

Entity Collector

    local context = Context.new()
    local group = context:get_group(Matcher({Position}))
    local pair = {}
    pair[group] = GroupEvent.ADDED|GroupEvent.REMOVED
    local collector = Collector.new(pair)
    local _entity = context:create_entity()
    _entity:add(Position,1,2,3)
    lu.assertEquals(collector.entities:size(),1)
    context:destroy_entity(_entity)
    lu.assertEquals(collector.entities:size(),0)
    collector:clear_entities()
    collector:deactivate()

Entity Index

    local context = Context.new()
    local group = context:get_group(Matcher({Person}))
    local index = EntityIndex.new(Person, group, 'age')
    context:add_entity_index(index)
    local adam = context:create_entity()
    adam:add(Person, 'Adam', 42)
    local eve = context:create_entity()
    eve:add(Person, 'Eve', 42)

    local idx = context:get_entity_index(Person)
    local entities = idx:get_entities(42)

    assert(entities:has(adam))
    assert(entities:has(eve))

Setup example

    -------------------------------------------
    local StartGame = class("StartGame")
    function StartGame:ctor(context)
        self.context = context
    end

    function StartGame:initialize()
        print("StartGame initialize")
        local entity = self.context:create_entity()
        entity:add(Movable,123)
    end

    -------------------------------------------
    local EndSystem = class("EndSystem")
    function EndSystem:ctor(context)
        self.context = context
    end

    function EndSystem:tear_down()
        print("EndSystem tear_down")
    end

    -------------------------------------------
    local MoveSystem = class("MoveSystem", ReactiveSystem)

    function MoveSystem:ctor(context)
        MoveSystem.super.ctor(self, context)
    end

    local trigger = {
        {
            Matcher({Movable}),
            GroupEvent.ADDED | GroupEvent.UPDATE
        }
    }

    function MoveSystem:get_trigger()
        return trigger
    end

    function MoveSystem:filter(entity)
        return entity:has(Movable)
    end

    function MoveSystem:execute(es)
        es:foreach(function( e  )
            print("ReactiveSystem: add entity with component Movable.",e)
        end)
    end

    local _context = Context.new()
    local systems = Systems.new()
    systems:add(StartGame.new(_context))
    systems:add(MoveSystem.new(_context))
    systems:add(EndSystem.new(_context))

    systems:initialize()

    systems:execute()

    systems:tear_down()