diff --git a/main.lua b/main.lua index e7614b0..f8db366 100644 --- a/main.lua +++ b/main.lua @@ -20,77 +20,72 @@ local Entity = Concord.entity local World = Concord.world local Worlds = Concord.worlds -Concord.loadComponents("test/components") +local test_comp_1 = Component(function(e, a) + e.a = a +end) local test_comp_2 = Component(function(e, a) e.a = a end) -Components.register("test_comp_2", test_comp_2) - local test_comp_3 = Component() -Components.register("test_comp_3", test_comp_3) +local test_system_1 = System({test_comp_1}) -local test_system = System({Components.test_comp_1}) -Systems.register("test_system", test_system) +function test_system_1:init() + self.pool.onEntityAdded = function() + + -local function onEntityAdded(pool, e) -- luacheck: ignore - print("Added") -end - -local function onEntityRemoved(pool, e) -- luacheck: ignore - print("Removed") -end - -function test_system:init() - self.pool.onEntityAdded = onEntityAdded - self.pool.onEntityRemoved = onEntityRemoved -end - -function test_system:update(dt) -- luacheck: ignore - --[=[ - for _, v in ipairs(self.pool) do - print(v) + print("Added to test_system 1") end - ]=] + self.pool.onEntityRemoved = function() print("Removed from test_system 1") end end -function test_system:update2(dt) -- luacheck: ignore - --print(#self.pool) +function test_system_1:test() + print("Running test_system_1 with: " ..#self.pool) + + for _, e in ipairs(self.pool) do + local newE = Entity() + newE:give(test_comp_1) + self:getWorld():addEntity(newE) + + e:give(test_comp_2) + end end + +local test_system_2 = System({test_comp_2}) + +function test_system_2:init() + self.pool.onEntityAdded = function(pool, e) print("Added to test_system 2") e:remove(test_comp_1) end + self.pool.onEntityRemoved = function() print("Removed from test_system 2") end +end + +function test_system_2:test() + print("Running test_system_2 with: " ..#self.pool) + + for _, e in ipairs(self.pool) do + end +end + local world = World() -Worlds.register("testWorld", world) local entity = Entity() -entity -:give(Components.test_comp_1, 100, 100) -:remove(Components.test_comp_1) -:give(Components.test_comp_1, 200, 100) -:give(Components.test_comp_3, 200, 100) +entity:give(test_comp_1, 100, 100) -Worlds.testWorld:addEntity(entity) +world:addEntity(entity) -world:addSystem(Systems.test_system, "update") -world:addSystem(Systems.test_system, "update", "update2") +world:addSystem(test_system_1, "test") +world:addSystem(test_system_2, "test") -function love.update(dt) - world:flush() +print("Iteration: 1") +world:emit("test") - world:emit("update", dt) -end +print("Iteration: 2") +world:emit("test") -function love.keypressed(key) - if key == "q" then - entity:remove(Components.test_comp_1) - end - if key == "w" then - entity:give(Components.test_comp_1) - end - if key == "e" then - world:removeEntity(entity) - end -end \ No newline at end of file +print("Iteration: 3") +world:emit("test") \ No newline at end of file diff --git a/src/entity.lua b/src/entity.lua index 98d1c97..b1db60c 100644 --- a/src/entity.lua +++ b/src/entity.lua @@ -13,10 +13,6 @@ function Entity.new() local e = setmetatable({ __world = nil, - __addedComponents = {}, - __removedComponents = {}, - __operations = {}, - __components = {}, __isDirty = false, @@ -29,32 +25,22 @@ function Entity.new() return e end -local function giveOperation(e, component) - local baseComponent = component.__baseComponent - - e[baseComponent] = component - e.__components[baseComponent] = component -end - -local function removeOperation(e, baseComponent) - e[baseComponent] = nil - e.__components[baseComponent] = nil -end - local function give(e, baseComponent, ...) local component = baseComponent:__initialize(...) - e.__addedComponents[#e.__addedComponents + 1] = component - e.__operations[#e.__operations + 1] = giveOperation + e[baseComponent] = component + e.__components[baseComponent] = component e.__isDirty = true + e:__dirty() end local function remove(e, baseComponent) - e.__removedComponents[#e.__removedComponents + 1] = baseComponent - e.__operations[#e.__operations + 1] = removeOperation + e[baseComponent] = nil + e.__components[baseComponent] = nil e.__isDirty = true + e:__dirty() end --- Gives an Entity a component with values. @@ -108,36 +94,22 @@ function Entity:assemble(assemblage, ...) return self end -function Entity:__flush() - local addi, removei = 1, 1 - - for i = 1, #self.__operations do - local operation = self.__operations[i] - - if (operation == giveOperation) then - operation(self, self.__addedComponents[addi]) - self.__addedComponents[addi] = nil - addi = addi + 1 - elseif (operation == removeOperation) then - operation(self, self.__removedComponents[removei]) - self.__removedComponents[removei] = nil - removei = removei + 1 - end - - self.__operations[i] = nil - end -end - --- Destroys the Entity. -- @return self function Entity:destroy() - if self.world then - self.world:removeEntity(self) + if self.__world then + self.__world:removeEntity(self) end return self end +function Entity:__dirty() + if self.__world then + self.__world:__dirtyEntity(self) + end +end + --- Gets a Component from the Entity. -- @param component The Component to get -- @return The Bag from the Component diff --git a/src/world.lua b/src/world.lua index 2fe1ca8..bf0eaf1 100644 --- a/src/world.lua +++ b/src/world.lua @@ -17,8 +17,9 @@ function World.new() events = {}, - __added = {}, - __removed = {}, + __added = List(), __backAdded = List(), + __removed = List(), __backRemoved = List(), + __dirty = List(), __backDirty = List(), __systemLookup = {}, @@ -36,14 +37,16 @@ function World:addEntity(e) error("bad argument #1 to 'World:addEntity' (Entity expected, got "..type(e)..")", 2) end - if e.world then + if e.__world then error("bad argument #1 to 'World:addEntity' (Entity was already added to a world)", 2) end - e.world = self + e.__world = self e.__wasAdded = true - self.entities:add(e) + self.__added:add(e) + + --self.entities:add(e) return self end @@ -58,50 +61,65 @@ function World:removeEntity(e) e.__wasRemoved = true + self.__removed:add(e) + return self end +function World:__dirtyEntity(e) + if not self.__dirty:has(e) then + self.__dirty:add(e) + end +end + + -- @return self -function World:flush() +function World:__flush() + -- Switch buffers + self.__added, self.__backAdded = self.__backAdded, self.__added + self.__removed, self.__backRemoved = self.__backRemoved, self.__removed + self.__dirty, self.__backDirty = self.__backDirty, self.__dirty + local e - for i = 1, self.entities.size do - e = self.entities:get(i) - if e.__isDirty then - e:__flush() + -- Added + for i = 1, self.__backAdded.size do + e = self.__backAdded:get(i) - if (not e.__wasAdded) then -- The __wasAdded check below will handle this instead - for j = 1, self.systems.size do - self.systems:get(j):__evaluate(e) - end - end + self.entities:add(e) - e.__isDirty = false + for j = 1, self.systems.size do + self.systems:get(j):__evaluate(e) end - if e.__wasAdded then - e.__wasAdded = false + self:onEntityAdded(e) + end + self.__backAdded:clear() - for j = 1, self.systems.size do - self.systems:get(j):__evaluate(e) - end + -- Removed + for i = 1, self.__backRemoved.size do + e = self.__backRemoved:get(i) - self:onEntityAdded(e) + e.__world = nil + self.entities:remove(e) + + for j = 1, self.systems.size do + self.systems:get(j):__remove(e) end - if e.__wasRemoved then - e.world = nil - self.entities:remove(e) + self:onEntityRemoved(e) + end + self.__backRemoved:clear() - for j = 1, self.systems.size do - self.systems:get(j):__remove(e) - end + -- Dirty + for i = 1, self.__backDirty.size do + e = self.__backDirty:get(i) - e.__wasRemoved = false - - self:onEntityRemoved(e) + for j = 1, self.systems.size do + self.systems:get(j):__evaluate(e) end end + self.__backDirty:clear() return self end @@ -246,6 +264,8 @@ function World:emit(callbackName, ...) local listener = listeners[i] if listener.enabled then + self:__flush() + listener.system[listener.callback](listener.system, ...) end end diff --git a/test/components/test_comp_1.lua b/test/components/test_comp_1.lua deleted file mode 100644 index ef9b98a..0000000 --- a/test/components/test_comp_1.lua +++ /dev/null @@ -1,6 +0,0 @@ -local Component = require("src").component - -return Component(function(e, x, y) - e.x = x - e.y = y -end) \ No newline at end of file