mirror of
https://github.com/bakpakin/tiny-ecs.git
synced 2026-07-22 07:56:52 -06:00
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:
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user