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

View file

@ -22,6 +22,12 @@ function Entity.new()
return e
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.
-- @param component The Component to add
-- @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)
end
local comp = component:__initialize(...)
self.components[component] = comp
self[component] = comp
if self[component] then
self:remove(component):apply()
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
end

View file

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

View file

@ -7,8 +7,6 @@ local mt = {__index = List}
-- @return A new list
function List.new()
return setmetatable({
objects = {},
pointers = {},
size = 0,
}, mt)
end
@ -16,8 +14,13 @@ end
--- Clears the List completely.
-- @return self
function List:clear()
self.objects = {}
self.pointers = {}
for i = 1, self.size do
local o = self[i]
self[o] = nil
self[i] = nil
end
self.size = 0
return self
@ -26,11 +29,11 @@ end
--- Adds an object to the List.
-- @param obj The object to add
-- @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
self.objects[size] = obj
self.pointers[obj] = size
self[size] = obj
self[obj] = size
self.size = size
return self
@ -40,22 +43,22 @@ end
-- @param obj The object to remove
-- @return self
function List:remove(obj)
local index = self.pointers[obj]
local index = self[obj]
if not index then return end
local size = self.size
if index == size then
self.objects[size] = nil
self[size] = nil
else
local other = self.objects[size]
local other = self[size]
self.objects[index] = other
self.pointers[other] = index
self[index] = other
self[other] = index
self.objects[size] = nil
self[size] = nil
end
self.pointers[obj] = nil
self[obj] = nil
self.size = size - 1
end
@ -63,14 +66,14 @@ end
-- @param index The index to look at
-- @return The object at the index
function List:get(index)
return self.objects[index]
return self[index]
end
--- Gets if the List has the object.
-- @param obj The object to search for
-- true if the list has the object, false otherwise
function List:has(obj)
return self.pointers[obj] and true
return self[obj] and true
end
return setmetatable(List, {

View file

@ -14,6 +14,9 @@ Pool.__index = Pool
function Pool.new(name, filter)
local pool = setmetatable(List(), Pool)
pool.added = {}
pool.removed = {}
pool.name = name
pool.filter = filter
@ -22,6 +25,12 @@ function Pool.new(name, filter)
return pool
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.
-- @param e The Entity to check
-- @return True if the entity is eligible, false otherwise

View file

@ -66,7 +66,7 @@ end
-- @param e The Entity to check
-- @return True if the Entity was added, false if it was removed. Nil if nothing happend
function System:__check(e)
local systemHas = self:__has(e)
local systemHas = self.__all[e]
for _, pool in ipairs(self.__pools) do
local poolHas = pool:has(e)
@ -74,23 +74,28 @@ function System:__check(e)
if not poolHas and eligible then
pool:add(e)
pool.added[#pool.added + 1] = e
self:entityAddedTo(e, pool)
self:__tryAdd(e)
elseif poolHas and not eligible then
pool:remove(e)
pool.removed[#pool.removed + 1] = e
self:entityRemovedFrom(e, pool)
self:__tryRemove(e)
end
end
end
--- Removed an Entity from the System.
--- Remove an Entity from the System.
-- @param e The Entity to remove
function System:__remove(e)
if self:__has(e) then
if self.__all[e] then
for _, pool in ipairs(self.__pools) do
if pool:has(e) then
pool:remove(e)
pool.removed[#pool.removed + 1] = e
self:entityRemovedFrom(e, pool)
end
end
@ -103,7 +108,7 @@ end
--- Tries to add an Entity to the System.
-- @param e The Entity to add
function System:__tryAdd(e)
if not self:__has(e) then
if not self.__all[e] then
self.__all[e] = 0
self:entityAdded(e)
end
@ -114,7 +119,7 @@ end
--- Tries to remove an Entity from the System.
-- @param e The Entity to remove
function System:__tryRemove(e)
if self:__has(e) then
if self.__all[e] then
self.__all[e] = self.__all[e] - 1
if self.__all[e] == 0 then
@ -124,19 +129,22 @@ function System:__tryRemove(e)
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.
-- @return The Instance
function System:getInstance()
return self.__instance
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.
-- @param ... Varags
function System:init(...)