From 2d21fe97a5ee616694ac755da8fbe68a5cdadc02 Mon Sep 17 00:00:00 2001 From: Justin van der Leij Date: Tue, 30 Jan 2018 12:45:35 +0100 Subject: [PATCH] Polishing --- fluid/component.lua | 2 +- fluid/entity.lua | 23 ++------- fluid/eventManager.lua | 21 -------- fluid/instance.lua | 24 ++------- fluid/list.lua | 11 ++--- fluid/pool.lua | 49 +++++-------------- fluid/system.lua | 8 +-- main.lua | 107 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 136 insertions(+), 109 deletions(-) diff --git a/fluid/component.lua b/fluid/component.lua index 689f516..a92a745 100644 --- a/fluid/component.lua +++ b/fluid/component.lua @@ -21,7 +21,7 @@ end -- Creates and initializes a new Bag. -- @param ... The values passed to the populate function -- @return A new initialized Bag -function Component:initialize(...) +function Component:__initialize(...) if self.__populate then local bag = {} self.__populate(bag, ...) diff --git a/fluid/entity.lua b/fluid/entity.lua index d53e60d..e29259e 100644 --- a/fluid/entity.lua +++ b/fluid/entity.lua @@ -1,22 +1,14 @@ -local Entity = { - entities = {}, -} +local Entity = {} Entity.__index = Entity --- Creates and initializes a new Entity. -- @return A new Entity function Entity.new() local e = setmetatable({ - id = #Entity.entities + 1, components = {}, - systems = {}, - keys = {}, - - instance = nil, + instance = nil, }, Entity) - Entity.entities[e.id] = e - return e end @@ -25,7 +17,7 @@ end -- @param ... The values passed to the Component -- @return self function Entity:give(component, ...) - self.components[component] = component:initialize(...) + self.components[component] = component:__initialize(...) return self end @@ -47,15 +39,6 @@ function Entity:check() return self end ---- Removed an Entity from the instance. --- @return self -function Entity:destroy() - Entity.entities[self.id] = nil - self.instance:destroyEntity(self) - - return self -end - --- Gets a Component from the Entity -- @param component The Component to get -- @return The Bag from the Component diff --git a/fluid/eventManager.lua b/fluid/eventManager.lua index d7b9540..d4b14f1 100644 --- a/fluid/eventManager.lua +++ b/fluid/eventManager.lua @@ -3,20 +3,12 @@ EventManager.__index = EventManager function EventManager.new() local eventManager = setmetatable({ - queue = {count = 0}, listeners = {}, }, EventManager) return eventManager end -function EventManager:push(event) - queue.count = queue.count + 1 - queue[queue.count] = event - - return self -end - function EventManager:emit(name, ...) local listeners = self.listeners[name] @@ -61,19 +53,6 @@ function EventManager:deregister(name, listener) return self end -function EventManager:process() - local queue = self.queue - - for i = 1, queue.count do - self:emit(queue[i]) - queue[i] = nil - end - - queue.count = 0 - - return self -end - return setmetatable(EventManager, { __call = function(_, ...) return EventManager.new(...) end, }) diff --git a/fluid/instance.lua b/fluid/instance.lua index a80f4ae..f90ef49 100644 --- a/fluid/instance.lua +++ b/fluid/instance.lua @@ -1,6 +1,6 @@ local PATH = (...):gsub('%.[^%.]+$', '') -local Pool = require(PATH..".pool") +local List = require(PATH..".list") local EventManager = require(PATH..".eventManager") local Instance = {} @@ -8,7 +8,7 @@ Instance.__index = Instance function Instance.new() local instance = setmetatable({ - entities = Pool(), + entities = List(), eventManager = EventManager(), systems = {}, @@ -26,16 +26,14 @@ end function Instance:checkEntity(e) for _, system in ipairs(self.systems) do - if system:entityUpdated(e) then - e.systems[#e.systems + 1] = system - end + system:checkEntity(e) end end -function Instance:destroyEntity(e) +function Instance:removeEntity(e) self.entities:remove(e) - for _, system in ipairs(e.systems) do + for _, system in ipairs(self.systems) do system:remove(e) end end @@ -69,18 +67,6 @@ function Instance:emit(...) return self end -function Instance:update(dt) - self:emit("update", dt) - - return self -end - -function Instance:draw() - self:emit("draw") - - return self -end - return setmetatable(Instance, { __call = function(_, ...) return Instance.new(...) end, }) diff --git a/fluid/list.lua b/fluid/list.lua index 50e7c41..af67bf5 100644 --- a/fluid/list.lua +++ b/fluid/list.lua @@ -34,18 +34,17 @@ function List:remove(obj) self.numerical[index] = other self.named[other] = index + + self.numerical[size] = nil end + self.named[obj] = nil self.size = size - 1 end -function List:get(i) - return self.numerical[i] -end - -function List:getIndex(obj) - return self.named[obj] +function List:has(obj) + return self.named[obj] and true end return setmetatable(List, { diff --git a/fluid/pool.lua b/fluid/pool.lua index 8b87d48..2f3eaf8 100644 --- a/fluid/pool.lua +++ b/fluid/pool.lua @@ -1,17 +1,21 @@ +local PATH = (...):gsub('%.[^%.]+$', '') + +local List = require(PATH..".list") + local Pool = {} Pool.__index = Pool function Pool.new(name, filter) - local pool = setmetatable({ - __filter = filter, - __name = name, - }, Pool) + local pool = setmetatable(List(), Pool) + pool.name = name + pool.filter = filter + return pool end function Pool:eligible(e) - for _, component in ipairs(self.__filter) do + for _, component in ipairs(self.filter) do if not e.components[component] then return false end @@ -20,38 +24,7 @@ function Pool:eligible(e) return true end -function Pool:add(e) - local key = #self + 1 - - self[key] = e - e.keys[self] = key -end - -function Pool:has(e) - return e.keys[self] and true -end - -function Pool:remove(e, pool) - local key = e.keys[self] - - if key then - local count = #self - - if key == count then - self[key] = nil - e.keys[self] = nil - else - local swap = self[count] - - self[key] = swap - self[count] = nil - swap.keys[self] = key - end - - return true - end -end - return setmetatable(Pool, { - __call = function(_, ...) return Pool.new(...) end, + __index = List, + __call = function(_, ...) return Pool.new(...) end, }) diff --git a/fluid/system.lua b/fluid/system.lua index 414fb08..eb0d775 100644 --- a/fluid/system.lua +++ b/fluid/system.lua @@ -14,11 +14,11 @@ function System.new(...) for _, filter in pairs({...}) do local pool = system:buildPool(filter) - if not system[pool.__name] then - system[pool.__name] = pool + if not system[pool.name] then + system[pool.name] = pool system.__pools[#system.__pools + 1] = pool else - error("Pool with name '"..pool.__name.."' already exists.") + error("Pool with name '"..pool.name.."' already exists.") end end @@ -40,7 +40,7 @@ function System:buildPool(pool) return Pool(name, filter) end -function System:entityUpdated(e) +function System:checkEntity(e) local systemHas = self:has(e) for _, pool in ipairs(self.__pools) do diff --git a/main.lua b/main.lua index e69de29..3a680bf 100644 --- a/main.lua +++ b/main.lua @@ -0,0 +1,107 @@ +local Fluid = require("fluid").init({ + useEvents = true +}) +local Entity = Fluid.entity +local Component = Fluid.component +local System = Fluid.system + +local Game = Fluid.instance() +Fluid.addInstance(Game) + +local Position = Component(function(e, x, y) + e.x = x + e.y = y +end) + +local Rectangle = Component(function(e, w, h) + e.w = w + e.h = h +end) + +local Circle = Component(function(e, r) + e.r = r +end) + +local Color = Component(function(e, r, g, b, a) + e.r = r + e.g = g + e.b = b + e.a = a +end) + +local RectangleRenderer = System({Position, Rectangle}) +function RectangleRenderer:draw() + for _, e in ipairs(self.pool.numerical) do + local position = e:get(Position) + local rectangle = e:get(Rectangle) + local color = e:get(Color) + + love.graphics.setColor(255, 255, 255) + if color then + love.graphics.setColor(color.r, color.g, color.b, color.a) + end + + love.graphics.rectangle("fill", position.x, position.y, rectangle.w, rectangle.h) + end +end + +local CircleRenderer = System({Position, Circle}) +function CircleRenderer:draw() + for _, e in ipairs(self.pool.numerical) do + local position = e:get(Position) + local circle = e:get(Circle) + local color = e:get(Color) + + love.graphics.setColor(255, 255, 255) + if color then + love.graphics.setColor(color.r, color.g, color.b, color.a) + end + + love.graphics.circle("fill", position.x, position.y, circle.r) + end +end + +local RandomRemover = System({}) +RandomRemover.time = 0 + +function RandomRemover:update(dt) + RandomRemover.time = RandomRemover.time + dt + + if RandomRemover.time >= 0.125 then + RandomRemover.time = 0 + + if self.pool.size > 0 then + local i = love.math.random(1, self.pool.size) + + Game:removeEntity(self.pool.numerical[i]) + end + end +end + +Game:addSystem(RandomRemover, "update") +Game:addSystem(RectangleRenderer, "draw") +Game:addSystem(CircleRenderer, "draw") + +for i = 1, 50 do + local e = Entity() + e:give(Position, love.math.random(0, 700), love.math.random(0, 700)) + e:give(Rectangle, love.math.random(5, 20), love.math.random(5, 20)) + + if love.math.random(0, 1) == 0 then + e:give(Color, love.math.random(0, 255), love.math.random(0, 255), love.math.random(0, 255), 255) + end + + Game:addEntity(e) +end + +for i = 1, 50 do + local e = Entity() + e:give(Position, love.math.random(0, 700), love.math.random(0, 700)) + e:give(Circle, love.math.random(5, 20)) + + if love.math.random(0, 1) == 0 then + e:give(Color, love.math.random(0, 255), love.math.random(0, 255), love.math.random(0, 255), 255) + end + + Game:addEntity(e) +end