Some ECS cleanup with ews() rework.
This commit is contained in:
parent
109d67bea9
commit
ff2b1d0180
210
src/ecs.lua
210
src/ecs.lua
|
@ -1,10 +1,29 @@
|
|||
local ENTITY_STORAGE = {}
|
||||
local PLACEHOLDER = {}
|
||||
|
||||
ecs = { }
|
||||
|
||||
local ALL_ENTITIES = {}
|
||||
|
||||
---@alias System { callback: fun(delta: number, a: any, b: any, c: any, d: any, e: any, any), shapes: {}, keys: string[], entityCache: table<any, boolean> }
|
||||
|
||||
---@type System[]
|
||||
local SYSTEMS = {}
|
||||
|
||||
local PLACEHOLDER = {}
|
||||
|
||||
-- TODO: Add entity to any existing systems
|
||||
function ecs.addEntity(entity)
|
||||
ENTITY_STORAGE[entity] = true
|
||||
ALL_ENTITIES[entity] = true
|
||||
for _, system in pairs(SYSTEMS) do
|
||||
if entityMatchesShapes(entity, system.shapes) then
|
||||
system.entityCache[entity] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ecs.removeEntity(entity)
|
||||
ALL_ENTITIES[entity] = nil
|
||||
for _, system in pairs(SYSTEMS) do
|
||||
system.entityCache[entity] = nil
|
||||
end
|
||||
end
|
||||
|
||||
---@return any
|
||||
|
@ -21,49 +40,15 @@ function allKeysIncluded(entity, filter)
|
|||
return true
|
||||
end
|
||||
|
||||
function allFiltersMatch(entity, filters)
|
||||
for _, filter in pairs(filters) do
|
||||
if not allKeysIncluded(entity, filter) then
|
||||
function entityMatchesShapes(entity, shapes)
|
||||
for _, shape in pairs(shapes) do
|
||||
if not allKeysIncluded(entity, shape) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@param shape T
|
||||
---@return fun(): T[]
|
||||
function ecs.buildEntityFilter(shape)
|
||||
local filters = {shape}
|
||||
return function()
|
||||
-- TODO? Cache all this?
|
||||
local ret = {}
|
||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
||||
if allFiltersMatch(entity, filters) then
|
||||
ret[#ret + 1] = entity;
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
---@generic T
|
||||
---@return fun(): T[]
|
||||
function ecs.buildRequiredFields(...)
|
||||
local filters = arg
|
||||
return function()
|
||||
-- TODO? Cache all this?
|
||||
local ret = {}
|
||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
||||
if allKeysIncluded(entity, filters) then
|
||||
ret[#ret + 1] = entity;
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
-- --@overload fun(tShape: `T`): fun(callback: fun(componentT: `T`))
|
||||
|
||||
---@generic T
|
||||
---@generic U
|
||||
---@generic V
|
||||
|
@ -73,11 +58,55 @@ end
|
|||
---@param vShape V?
|
||||
---@param wShape W?
|
||||
---@return fun(callback: fun(componentT: T, componentU: U, componentV: V, componentW: W))
|
||||
function ecs.entitiesWithShapes(tShape, uShape, vShape, wShape)
|
||||
function ecs.entitiesHavingShapes(tShape, uShape, vShape, wShape)
|
||||
return function()
|
||||
end
|
||||
end
|
||||
|
||||
-- Print contents of `tbl`, with indentation.
|
||||
-- `indent` sets the initial level of indentation.
|
||||
function tprint (tbl, indent)
|
||||
if not indent then indent = 0 end
|
||||
for k, v in pairs(tbl) do
|
||||
formatting = string.rep(" ", indent) .. k .. ": "
|
||||
if type(v) == "table" then
|
||||
print(formatting)
|
||||
tprint(v, indent+1)
|
||||
elseif type(v) == 'boolean' then
|
||||
print(formatting .. tostring(v))
|
||||
else
|
||||
print(formatting .. v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function addSystem(callback, keys, shapes)
|
||||
SYSTEMS[#SYSTEMS + 1] = {
|
||||
callback = callback,
|
||||
keys = keys,
|
||||
shapes = shapes,
|
||||
entityCache = nil
|
||||
}
|
||||
end
|
||||
|
||||
---@param deltaSeconds number
|
||||
function ecs.update(deltaSeconds)
|
||||
for _,system in pairs(SYSTEMS) do
|
||||
if not system.entityCache then
|
||||
system.entityCache = {}
|
||||
for entity,_ in pairs(ALL_ENTITIES) do
|
||||
if entityMatchesShapes(entity, system.shapes) then
|
||||
system.entityCache[entity] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
for entity,_ in pairs(system.entityCache) do
|
||||
local keys = system.keys
|
||||
system.callback(deltaSeconds, entity[keys[1]], entity[keys[2]], entity[keys[3]], entity[keys[4]], entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a function that accepts a callback. This callback will receive one argument for each Shape provided.
|
||||
---
|
||||
---@generic T
|
||||
|
@ -89,82 +118,51 @@ end
|
|||
---@generic W
|
||||
---@generic WKey
|
||||
---@param tShape { [TKey]: T }
|
||||
---@param uShape { [UKey]: U }?
|
||||
---@param vShape { [VKey]: V }?
|
||||
---@param wShape { [WKey]: W }?
|
||||
---@return fun(callback: fun(componentT: T, componentU: U, componentV: V, componentW: W))
|
||||
function ecs.entitiesWithShapes2(tShape, uShape, vShape, wShape)
|
||||
local filters = {tShape, uShape, vShape, wShape}
|
||||
return function(callback)
|
||||
-- TODO? Cache all this?
|
||||
local ret = {}
|
||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
||||
if allFiltersMatch(entity, filters) then
|
||||
callback(entity, entity, entity, entity)
|
||||
---@param uShape { [UKey]: U } | fun(componentT: T, any) | nil
|
||||
---@param vShape { [VKey]: V } | fun(componentT: T, componentU: U, any) | nil
|
||||
---@param wShape { [WKey]: W } | fun(componentT: T, componentU: U, componentV: V, any) | nil
|
||||
---@param finalFunc fun(componentT: T, componentU: U, componentV: V, componentW: W, any) | nil
|
||||
function ecs.entitiesWithShapes(tShape, uShape, vShape, wShape, finalFunc)
|
||||
local maybeShapes = {tShape, uShape, vShape, wShape, finalFunc}
|
||||
local shapes = {}
|
||||
local callback
|
||||
|
||||
for _,maybeShape in pairs(maybeShapes) do
|
||||
if type(maybeShape) == "table" then
|
||||
shapes[#shapes + 1] = maybeShape
|
||||
elseif type(maybeShape) == "function" then
|
||||
callback = maybeShape
|
||||
end
|
||||
end
|
||||
return ret
|
||||
|
||||
local keys = {}
|
||||
for _,shape in pairs(shapes) do
|
||||
for key,_ in pairs(shape) do
|
||||
keys[#keys + 1] = key
|
||||
end
|
||||
end
|
||||
|
||||
addSystem(callback, keys, shapes)
|
||||
end
|
||||
|
||||
local f = ecs.field()
|
||||
|
||||
---@alias XYPair { x:number, y: number }
|
||||
|
||||
---@type XYPair
|
||||
---@type { x: number, y: number }
|
||||
local XYPair = { x = f, y = f }
|
||||
|
||||
local HasPosition = { position = XYPair }
|
||||
local HasVelocity = { velocity = XYPair }
|
||||
local Position = { position = XYPair }
|
||||
local Velocity = { velocity = XYPair }
|
||||
|
||||
local entIt = ecs.entitiesWithShapes(HasPosition, HasVelocity)
|
||||
entIt(function(hasPos, hasVel)
|
||||
hasPos.position.x = hasPos.position.x + hasVel.velocity.y
|
||||
end)
|
||||
|
||||
local entIt2 = ecs.entitiesWithShapes2(HasPosition)
|
||||
entIt2(function(position, velocity)
|
||||
---@type number
|
||||
local num = 0
|
||||
num = position.x
|
||||
num = velocity.z
|
||||
print(num)
|
||||
end)
|
||||
|
||||
---@return fun(callback: fun(T))
|
||||
function ecs.entitiesWithFields(...)
|
||||
local filters = {...}
|
||||
return function(callback)
|
||||
-- TODO? Cache all this?
|
||||
for entity,_ in pairs(ENTITY_STORAGE) do
|
||||
if allKeysIncluded(entity, filters) then
|
||||
callback(entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@type unknown
|
||||
function ecs.shape(...)
|
||||
local shape = {}
|
||||
for _,incomingShape in ipairs(arg) do
|
||||
for k,v in pairs(incomingShape) do
|
||||
shape[k] = v
|
||||
end
|
||||
end
|
||||
return shape
|
||||
end
|
||||
|
||||
local exampleEntity = {
|
||||
local someMovable = {
|
||||
position = { x = 0, y = 0 },
|
||||
velocity = { x = 1, y = 1 }
|
||||
velocity = { x = 2, y = 1 }
|
||||
}
|
||||
|
||||
ecs.addEntity(exampleEntity)
|
||||
ecs.addEntity(someMovable)
|
||||
|
||||
---@type fun(system: fun(entity: { position: XYPair, velocity: XYPair }))
|
||||
local forEachPosVel = ecs.entitiesWithFields('position', 'velocity')
|
||||
|
||||
forEachPosVel(function(hasVelPos)
|
||||
print(hasVelPos.velocity.x)
|
||||
ecs.entitiesWithShapes(Position, Velocity, function (delta, pos, vel)
|
||||
print("position:")
|
||||
tprint(pos, 1)
|
||||
pos.x = pos.x + (vel.x * delta)
|
||||
pos.y = pos.y + (vel.y * delta)
|
||||
end)
|
Loading…
Reference in New Issue