Skip to content

Instantly share code, notes, and snippets.

@FollowCD
Forked from CarlLee/ecs.lua
Created June 17, 2019 10:00
Show Gist options
  • Save FollowCD/f9849f325b23f5c9a6e98d13e90464b9 to your computer and use it in GitHub Desktop.
Save FollowCD/f9849f325b23f5c9a6e98d13e90464b9 to your computer and use it in GitHub Desktop.

Revisions

  1. @CarlLee CarlLee revised this gist Jun 17, 2019. 1 changed file with 38 additions and 0 deletions.
    38 changes: 38 additions & 0 deletions test.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@


    local World = require("ecs").World

    local w = World:new()

    w:register_components({
    transform = 0,
    rotation = 1
    })

    local e1 = w:new_entity()
    local e2 = w:new_entity()

    e1:add_component("transform", {x = 0, y = 0, z = 9})

    e2:add_component("transform", {x = 0, y = 0, z = 9})
    e2:add_component("rotation", {angle = 0})

    function tick(entities, dT)
    for i, e in ipairs(entities) do
    e.transform.x = e.transform.x + dT
    end
    end

    local s = {
    tick = tick,
    components = {"transform", "rotation"}
    }

    w:add_system(s)

    w:tick(0.5)
    print(e1.transform.x)
    print(e2.transform.x)
    w:tick(0.56)
    print(e1.transform.x)
    print(e2.transform.x)
  2. @CarlLee CarlLee created this gist Jun 17, 2019.
    114 changes: 114 additions & 0 deletions ecs.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,114 @@
    local Entity = {
    }
    local EntityMeta = {
    __index = function(entity, key)
    local o = rawget(Entity, key)
    if(o ~= nil) then
    return o
    end
    local component_id = key
    if(type(component_id) == "string") then
    component_id = entity:lookup_component_id(key)
    if(component_id == nil) then
    return nil
    end
    end
    local component_index = entity.component_indices[component_id]
    if(component_index ~= nil) then
    local components = entity.world.components[component_id]
    if(components ~= nil) then
    return components[component_index]
    end
    end
    return nil
    end
    }

    function Entity:new(world)
    local o = {}
    o.world = world
    o.component_indices = {}
    setmetatable(o, EntityMeta)
    return o
    end

    function Entity:add_component(key, c)
    local component_id = key
    if(type(component_id) == "string") then
    component_id = self:lookup_component_id(component_id)
    end
    if(component_id == nil) then
    return
    end
    local world = self.world
    local components = world.components[component_id]
    if(components == nil) then
    components = {}
    world.components[component_id] = components
    end
    table.insert(components, c)
    local idx = #components
    self.component_indices[component_id] = idx
    self.mask = self.mask or 0
    self.mask = self.mask | (1 << component_id)
    end

    function Entity:lookup_component_id(name)
    return self.world.component_map[name]
    end

    local World = {
    }

    function World:new(o)
    local o = o or {
    entities = {},
    components = {},
    systems = {},
    component_map = {}
    }
    setmetatable(o, {__index = World})
    return o
    end

    function World:new_entity()
    local e = Entity:new(self)
    table.insert(self.entities, e)
    return e
    end

    function World:add_system(s)
    table.insert(self.systems, s)
    s.mask = self:generate_mask(s.components)
    end

    function World:register_components(m)
    self.component_map = m
    end

    function World:generate_mask(components)
    local mask = 0
    for i, v in ipairs(components) do
    local component_id = self.component_map[v]
    if(component_id ~= nil) then
    mask = mask | (1 << component_id)
    end
    end
    return mask
    end

    function World:tick(dT)
    for system_idx, system in ipairs(self.systems) do
    local entities = {}
    for entity_idx, entity in ipairs(self.entities) do
    if(system.mask & ~entity.mask == 0) then
    table.insert(entities, entity)
    end
    end
    system.tick(entities, dT)
    end
    end

    return {
    World = World
    }