Optimized Lists. Added pool.added and .removed. Added entity:ensure

This commit is contained in:
Justin van der Leij 2018-10-02 21:52:23 +02:00
parent e2b7af87fd
commit 11255fd722
7 changed files with 104 additions and 48 deletions

8
TODO Normal file
View file

@ -0,0 +1,8 @@
[x] Modify pools and list to be more efficient
[x] Rework Entity:give to remove any previous component and re-add it.
[x] Add Entity:ensure (maybe?)
[ ] Put pools in the Instance and invert dependency.
[ ] Share pools between systems
[ ] Remove System callbacks
[x] Put .added and .removed in pools so they can be iterated over
[ ] Implement assemblages

View file

@ -31,10 +31,7 @@ end)
local RectangleRenderer = System({Position, Rectangle}) local RectangleRenderer = System({Position, Rectangle})
function RectangleRenderer:draw() function RectangleRenderer:draw()
local e for _, e in ipairs(self.pool) do
for i = 1, self.pool.size do
e = self.pool:get(i)
local position = e:get(Position) local position = e:get(Position)
local rectangle = e:get(Rectangle) local rectangle = e:get(Rectangle)
local color = e:get(Color) local color = e:get(Color)
@ -49,11 +46,16 @@ function RectangleRenderer:draw()
end end
local CircleRenderer = System({Position, Circle}) local CircleRenderer = System({Position, Circle})
function CircleRenderer:draw() function CircleRenderer:flush()
local e for _, e in ipairs(self.pool.removed) do
for i = 1, self.pool.size do print(tostring(e).. " was removed from my pool D:")
e = self.pool:get(i) end
self:clear()
end
function CircleRenderer:draw()
for _, e in ipairs(self.pool) do
local position = e:get(Position) local position = e:get(Position)
local circle = e:get(Circle) local circle = e:get(Circle)
local color = e:get(Color) local color = e:get(Color)
@ -76,7 +78,7 @@ end
function RandomRemover:update(dt) function RandomRemover:update(dt)
self.time = self.time + dt self.time = self.time + dt
if self.time >= 0.25 then if self.time >= 0.5 then
self.time = 0 self.time = 0
if self.pool.size > 0 then if self.pool.size > 0 then
@ -115,4 +117,4 @@ for i = 1, 100 do
end end
Game:addEntity(e) Game:addEntity(e)
end end

View file

@ -22,6 +22,12 @@ function Entity.new()
return e return e
end end
local function give(e, component, ...)
local comp = component:__initialize(...)
e.components[component] = comp
e[component] = comp
end
--- Gives an Entity a component with values. --- Gives an Entity a component with values.
-- @param component The Component to add -- @param component The Component to add
-- @param ... The values passed to the Component -- @param ... The values passed to the Component
@ -31,9 +37,25 @@ function Entity:give(component, ...)
error("bad argument #1 to 'Entity:give' (Component expected, got "..type(component)..")", 2) error("bad argument #1 to 'Entity:give' (Component expected, got "..type(component)..")", 2)
end end
local comp = component:__initialize(...) if self[component] then
self.components[component] = comp self:remove(component):apply()
self[component] = comp end
give(self, component, ...)
return self
end
function Entity:ensure(component, ...)
if not Type.isComponent(component) then
error("bad argument #1 to 'Entity:ensure' (Component expected, got "..type(component)..")", 2)
end
if self[component] then
return self
end
give(self, component, ...)
return self return self
end end

View file

@ -92,6 +92,10 @@ function Instance:flush()
end end
end end
for i = 1, self.systems.size do
self.systems:get(i):flush()
end
return self return self
end end

View file

@ -7,18 +7,21 @@ local mt = {__index = List}
-- @return A new list -- @return A new list
function List.new() function List.new()
return setmetatable({ return setmetatable({
objects = {}, size = 0,
pointers = {},
size = 0,
}, mt) }, mt)
end end
--- Clears the List completely. --- Clears the List completely.
-- @return self -- @return self
function List:clear() function List:clear()
self.objects = {} for i = 1, self.size do
self.pointers = {} local o = self[i]
self.size = 0
self[o] = nil
self[i] = nil
end
self.size = 0
return self return self
end end
@ -26,12 +29,12 @@ end
--- Adds an object to the List. --- Adds an object to the List.
-- @param obj The object to add -- @param obj The object to add
-- @return self -- @return self
function List:add(obj) function List:add(obj) -- obj can not be a number and also not the string "size"
local size = self.size + 1 local size = self.size + 1
self.objects[size] = obj self[size] = obj
self.pointers[obj] = size self[obj] = size
self.size = size self.size = size
return self return self
end end
@ -40,22 +43,22 @@ end
-- @param obj The object to remove -- @param obj The object to remove
-- @return self -- @return self
function List:remove(obj) function List:remove(obj)
local index = self.pointers[obj] local index = self[obj]
if not index then return end if not index then return end
local size = self.size local size = self.size
if index == size then if index == size then
self.objects[size] = nil self[size] = nil
else else
local other = self.objects[size] local other = self[size]
self.objects[index] = other self[index] = other
self.pointers[other] = index self[other] = index
self.objects[size] = nil self[size] = nil
end end
self.pointers[obj] = nil self[obj] = nil
self.size = size - 1 self.size = size - 1
end end
@ -63,14 +66,14 @@ end
-- @param index The index to look at -- @param index The index to look at
-- @return The object at the index -- @return The object at the index
function List:get(index) function List:get(index)
return self.objects[index] return self[index]
end end
--- Gets if the List has the object. --- Gets if the List has the object.
-- @param obj The object to search for -- @param obj The object to search for
-- true if the list has the object, false otherwise -- true if the list has the object, false otherwise
function List:has(obj) function List:has(obj)
return self.pointers[obj] and true return self[obj] and true
end end
return setmetatable(List, { return setmetatable(List, {

View file

@ -14,6 +14,9 @@ Pool.__index = Pool
function Pool.new(name, filter) function Pool.new(name, filter)
local pool = setmetatable(List(), Pool) local pool = setmetatable(List(), Pool)
pool.added = {}
pool.removed = {}
pool.name = name pool.name = name
pool.filter = filter pool.filter = filter
@ -22,6 +25,12 @@ function Pool.new(name, filter)
return pool return pool
end end
function Pool:flush()
for i = 1, math.max(#self.added, #self.removed) do
self.added[i], self.removed[i] = nil, nil
end
end
--- Checks if an Entity is eligible for the Pool. --- Checks if an Entity is eligible for the Pool.
-- @param e The Entity to check -- @param e The Entity to check
-- @return True if the entity is eligible, false otherwise -- @return True if the entity is eligible, false otherwise

View file

@ -66,7 +66,7 @@ end
-- @param e The Entity to check -- @param e The Entity to check
-- @return True if the Entity was added, false if it was removed. Nil if nothing happend -- @return True if the Entity was added, false if it was removed. Nil if nothing happend
function System:__check(e) function System:__check(e)
local systemHas = self:__has(e) local systemHas = self.__all[e]
for _, pool in ipairs(self.__pools) do for _, pool in ipairs(self.__pools) do
local poolHas = pool:has(e) local poolHas = pool:has(e)
@ -74,23 +74,28 @@ function System:__check(e)
if not poolHas and eligible then if not poolHas and eligible then
pool:add(e) pool:add(e)
pool.added[#pool.added + 1] = e
self:entityAddedTo(e, pool) self:entityAddedTo(e, pool)
self:__tryAdd(e) self:__tryAdd(e)
elseif poolHas and not eligible then elseif poolHas and not eligible then
pool:remove(e) pool:remove(e)
pool.removed[#pool.removed + 1] = e
self:entityRemovedFrom(e, pool) self:entityRemovedFrom(e, pool)
self:__tryRemove(e) self:__tryRemove(e)
end end
end end
end end
--- Removed an Entity from the System. --- Remove an Entity from the System.
-- @param e The Entity to remove -- @param e The Entity to remove
function System:__remove(e) function System:__remove(e)
if self:__has(e) then if self.__all[e] then
for _, pool in ipairs(self.__pools) do for _, pool in ipairs(self.__pools) do
if pool:has(e) then if pool:has(e) then
pool:remove(e) pool:remove(e)
pool.removed[#pool.removed + 1] = e
self:entityRemovedFrom(e, pool) self:entityRemovedFrom(e, pool)
end end
end end
@ -103,7 +108,7 @@ end
--- Tries to add an Entity to the System. --- Tries to add an Entity to the System.
-- @param e The Entity to add -- @param e The Entity to add
function System:__tryAdd(e) function System:__tryAdd(e)
if not self:__has(e) then if not self.__all[e] then
self.__all[e] = 0 self.__all[e] = 0
self:entityAdded(e) self:entityAdded(e)
end end
@ -114,7 +119,7 @@ end
--- Tries to remove an Entity from the System. --- Tries to remove an Entity from the System.
-- @param e The Entity to remove -- @param e The Entity to remove
function System:__tryRemove(e) function System:__tryRemove(e)
if self:__has(e) then if self.__all[e] then
self.__all[e] = self.__all[e] - 1 self.__all[e] = self.__all[e] - 1
if self.__all[e] == 0 then if self.__all[e] == 0 then
@ -124,19 +129,22 @@ function System:__tryRemove(e)
end end
end end
function System:flush()
self:clear()
end
function System:clear()
for i = 1, #self.__pools do
self.__pools[i]:flush()
end
end
--- Returns the Instance the System is in. --- Returns the Instance the System is in.
-- @return The Instance -- @return The Instance
function System:getInstance() function System:getInstance()
return self.__instance return self.__instance
end end
--- Returns if the System has the Entity.
-- @param e The Entity to check for
-- @return True if the System has the Entity. False otherwise
function System:__has(e)
return self.__all[e] and true
end
--- Default callback for system initialization. --- Default callback for system initialization.
-- @param ... Varags -- @param ... Varags
function System:init(...) function System:init(...)
@ -170,12 +178,12 @@ function System:addedTo(instance)
end end
-- Default callback for when a System's callback is enabled. -- Default callback for when a System's callback is enabled.
-- @param callbackName The name of the callback that was enabled -- @param callbackName The name of the callback that was enabled
function System:enabledCallback(callbackName) function System:enabledCallback(callbackName)
end end
-- Default callback for when a System's callback is disabled. -- Default callback for when a System's callback is disabled.
-- @param callbackName The name of the callback that was disabled -- @param callbackName The name of the callback that was disabled
function System:disabledCallback(callbackName) function System:disabledCallback(callbackName)
end end