Remove dependency on IDs in Systems and Entities.

This allows Systems to be reused in multiple worlds.
Fix a few bugs.
Remove World:change(...)
This commit is contained in:
bakpakin
2015-03-28 22:54:34 +08:00
parent e8b4b7f106
commit c046bde701
2 changed files with 51 additions and 68 deletions
+50 -67
View File
@@ -1,15 +1,17 @@
local jojo = { local jojo = {
_VERSION = "0.0.2", _VERSION = "0.0.3",
_URL = "https://github.com/bakpakin/Jojo" _URL = "https://github.com/bakpakin/Jojo",
_DESCRIPTION = "Entity Component System for lua."
} }
-- Simplified class implementation with no inheritance or polymorphism. -- Simplified class implementation with no inheritance or polymorphism.
local setmetatable = setmetatable local setmetatable = setmetatable
local function class() local function class(name)
local c = {} local c = {}
local mt = {} local mt = {}
setmetatable(c, mt) setmetatable(c, mt)
c.__index = c c.__index = c
c.name = name
function mt.__call(_, ...) function mt.__call(_, ...)
local newobj = {} local newobj = {}
setmetatable(newobj, c) setmetatable(newobj, c)
@@ -21,9 +23,9 @@ local function class()
return c return c
end end
local World = class() local World = class("World")
local Aspect = class() local Aspect = class("Aspect")
local System = class() local System = class("System")
jojo.World = World jojo.World = World
jojo.Aspect = Aspect jojo.Aspect = Aspect
@@ -168,8 +170,6 @@ end
----- System ----- ----- System -----
System.nextID = 0
-- System(preupdate, update, [aspect, addCallback, removeCallback]) -- System(preupdate, update, [aspect, addCallback, removeCallback])
-- Creates a new System with the given aspect and update callback. The update -- Creates a new System with the given aspect and update callback. The update
@@ -186,15 +186,10 @@ function System:init(preupdate, update, aspect, add, remove)
self.active = true self.active = true
self.add = add self.add = add
self.remove = remove self.remove = remove
local id = System.nextID
self.id = id
System.nextID = id + 1
end end
function System:__tostring() function System:__tostring()
return "JojoSystem<id: ".. return "JojoSystem<preupdate: " ..
self.id ..
"preupdate: " ..
self.preupdate .. self.preupdate ..
", update: " .. ", update: " ..
self.update .. self.update ..
@@ -215,10 +210,10 @@ function World:init(...)
local args = {...} local args = {...}
-- Table of Entity IDs to status -- Table of Entities to status
self.status = {} self.status = {}
-- Table of Entity IDs to Entities -- Set of Entities
self.entities = {} self.entities = {}
-- Number of Entities in World. -- Number of Entities in World.
@@ -227,27 +222,23 @@ function World:init(...)
-- List of Systems -- List of Systems
self.systems = args self.systems = args
-- Table of System IDs to System Indices -- Table of Systems to System Indices
local systemIndices = {} local systemIndices = {}
self.systemIndices = systemIndices self.systemIndices = systemIndices
-- Next available entity ID -- Table of Systems to Sets of matching Entities
self.nextID = 0
-- Table of System IDs to Sets of matching Entity IDs
local systemEntities = {} local systemEntities = {}
self.systemEntities = systemEntities self.systemEntities = systemEntities
for i, sys in ipairs(args) do for i, sys in ipairs(args) do
local id = sys.id systemEntities[sys] = {}
systemEntities[id] = {} systemIndices[sys] = i
systemIndices[id] = i
end end
-- List of Systems to add next update -- List of Systems to add next update
self.systemsToAdd = {} self.systemsToAdd = {}
-- List of System ids to remove next update -- List of Systems to remove next update
self.systemsToRemove = {} self.systemsToRemove = {}
end end
@@ -287,17 +278,15 @@ end
-- World:add(...) -- World:add(...)
-- Adds Entities to the World. Entities will enter the World the next time -- Adds Entities to the World. Entities will enter the World the next time
-- World:update(dt) is called. -- World:update(dt) is called. Also call this method when an Entity has had its
-- Components changed, such that it matches different Aspects.
function World:add(...) function World:add(...)
local args = {...} local args = {...}
local status = self.status local status = self.status
local entities = self.entities local entities = self.entities
for _, e in ipairs(args) do for _, e in ipairs(args) do
local id = self.nextID entities[e] = true
self.nextID = id + 1 status[e] = "add"
e.id = id
entities[id] = e
status[id] = "add"
end end
end end
@@ -310,7 +299,7 @@ function World:change(...)
local args = {...} local args = {...}
local status = self.status local status = self.status
for _, e in ipairs(args) do for _, e in ipairs(args) do
status[e.id] = "add" status[e] = "add"
end end
end end
@@ -322,7 +311,7 @@ function World:remove(...)
local args = {...} local args = {...}
local status = self.status local status = self.status
for _, e in ipairs(args) do for _, e in ipairs(args) do
status[e.id] = "remove" status[e] = "remove"
end end
end end
@@ -339,10 +328,10 @@ function World:updateSystem(system, dt)
if update then if update then
local entities = self.entities local entities = self.entities
local eids = systemEntities[system.id] local es = systemEntities[system]
if eids then if es then
for eid in pairs(eids) do for e in pairs(es) do
update(entities[eid], dt) update(e, dt)
end end
end end
end end
@@ -367,19 +356,17 @@ function World:update(dt)
local sys = systemsToRemove[i] local sys = systemsToRemove[i]
systemsToRemove[i] = nil systemsToRemove[i] = nil
local sysIndex = systemIndices[sys]
local id = sys.id
local sysIndex = systemIndices[id]
tremove(systems, sysIndex) tremove(systems, sysIndex)
local removec = sys.remove local removeCallback = sys.remove
if removec then -- call 'remove' on all entities in the System if removeCallback then -- call 'remove' on all entities in the System
for eid in pairs(systemEntities[id]) do for e in pairs(systemEntities[sys]) do
removec(entities[eid]) removeCallback(e)
end end
end end
systemEntities[id] = nil systemEntities[sys] = nil
end end
-- Add Systems queued for addition -- Add Systems queued for addition
@@ -389,15 +376,14 @@ function World:update(dt)
systemsToAdd[i] = nil systemsToAdd[i] = nil
-- Add system to world -- Add system to world
local id = sys.id local es = {}
local eids = {} systemEntities[sys] = es
systemEntities[id] = eids
tinsert(systems, sys) tinsert(systems, sys)
systemIndices[id] = #systems systemIndices[sys] = #systems
local a = sys.aspect local a = sys.aspect
for eid, e in pairs(entities) do for e in pairs(entities) do
eids[eid] = a:matches(e) and true or nil es[e] = a:matches(e) and true or nil
end end
end end
@@ -405,32 +391,29 @@ function World:update(dt)
local deltaEntityCount = 0 local deltaEntityCount = 0
-- Add, remove, or change Entities -- Add, remove, or change Entities
for eid, s in pairs(statuses) do for e, s in pairs(statuses) do
local e = entities[eid]
if s == "add" then if s == "add" then
deltaEntityCount = deltaEntityCount + 1 deltaEntityCount = deltaEntityCount + 1
for sysID, eids in pairs(systemEntities) do for sys, es in pairs(systemEntities) do
local sys = systems[systemIndices[sysID]]
local matches = sys.aspect:matches(e) and true or nil local matches = sys.aspect:matches(e) and true or nil
local addc = sys.add local addCallback = sys.add
if addc and matches and not eids[eid] then if addCallback and matches and not es[e] then
addc(e) addCallback(e)
end end
eids[eid] = matches es[e] = matches
end end
elseif s == "remove" then elseif s == "remove" then
deltaEntityCount = deltaEntityCount - 1 deltaEntityCount = deltaEntityCount - 1
entities[eid] = nil entities[e] = nil
for sysID, eids in pairs(systemEntities) do for sys, es in pairs(systemEntities) do
local sys = systems[systemIndices[sysID]]
local removec = sys.remove local removec = sys.remove
if removec then if removec then
removec(e) removec(e)
end end
eids[eid] = nil es[e] = nil
end end
end end
statuses[eid] = nil statuses[e] = nil
end end
-- Update Entity count -- Update Entity count
@@ -450,8 +433,8 @@ end
-- all Entities will be removed. -- all Entities will be removed.
function World:clearEntities() function World:clearEntities()
local status = self.status local status = self.status
for eid in pairs(self.entity) do for e in pairs(self.entities) do
status[eid] = "remove" status[e] = "remove"
end end
end end
@@ -463,7 +446,7 @@ function World:clearSystems()
local newSystemsToRemove = {} local newSystemsToRemove = {}
local systems = self.systems local systems = self.systems
for i = 1, #systems do for i = 1, #systems do
newSystemsToRemove[i] = systems[i].id newSystemsToRemove[i] = systems[i]
end end
self.systemsToRemove = newSystemsToRemove self.systemsToRemove = newSystemsToRemove
end end
+1 -1
View File
@@ -75,7 +75,7 @@ local moves = System(
amove amove
) )
local world = World(moves) local world = World(moves, System(nil, nil, aall))
world:add(e1, e2, e3) world:add(e1, e2, e3)
world:update(21) world:update(21)