Update tiny-ecs to 1.1-2

This commit is contained in:
bakpakin 2015-05-17 08:13:19 +08:00
parent a63329422d
commit be56780b88
10 changed files with 344 additions and 172 deletions

View File

@ -1,14 +1,39 @@
--[[
Copyright (c) 2015 Calvin Rose
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
--- @module tiny-ecs --- @module tiny-ecs
-- @author Calvin Rose -- @author Calvin Rose
local tiny = { _VERSION = "1.0-2" } -- @license MIT
-- @copyright 2015
local tiny = { _VERSION = "1.1-2" }
-- Local versions of standard lua functions -- Local versions of standard lua functions
local tinsert = table.insert local tinsert = table.insert
local tremove = table.remove local tremove = table.remove
local tsort = table.sort
local pairs = pairs local pairs = pairs
local ipairs = ipairs local ipairs = ipairs
local setmetatable = setmetatable local setmetatable = setmetatable
local type = type local type = type
local select = select
-- Local versions of the library functions -- Local versions of the library functions
local tiny_manageEntities local tiny_manageEntities
@ -22,20 +47,57 @@ local tiny_remove
--- Filter functions. --- Filter functions.
-- A Filter is a function that selects which Entities apply to a System. -- A Filter is a function that selects which Entities apply to a System.
-- Filters take two parameters, the System and the Entity, and return a boolean
-- value indicating if the Entity should be processed by the System.
--
-- Filters must be added to Systems by setting the `filter` field of the System.
-- Filter's returned by `tiny.requireAll` and `tiny.requireAny` are immutable
-- and can be used by multiple Systems.
--
-- local f1 = tiny.requireAll("position", "velocity", "size")
-- local f2 = tiny.requireAny("position", "velocity", "size")
--
-- local e1 = {
-- position = {2, 3},
-- velocity = {3, 3},
-- size = {4, 4}
-- }
--
-- local entity2 = {
-- position = {4, 5},
-- size = {4, 4}
-- }
--
-- local e3 = {
-- position = {2, 3},
-- velocity = {3, 3}
-- }
--
-- print(f1(nil, e1), f1(nil, e2), f1(nil, e3)) -- prints true, false, false
-- print(f2(nil, e1), f2(nil, e2), f2(nil, e3)) -- prints true, true, true
--
-- Filters can also be passed as arguments to other Filter constructors. This is
-- a powerful way to create complex, custom Filters that select a very specific
-- set of Entities.
--
-- -- Selects Entities with an "image" Component, but not Entities with a
-- -- "Player" or "Enemy" Component.
-- filter = tiny.requireAll("image", tiny.rejectAny("Player", "Enemy"))
--
-- @section Filter -- @section Filter
--- Makes a Filter that filters Entities with specified Components. --- Makes a Filter that selects Entities with all specified Components and
-- An Entity must have all Components to match the filter. -- Filters.
-- @param ... List of Components -- @param ... List of required Components and other Filters.
function tiny.requireAll(...) function tiny.requireAll(...)
local components = {...} local components = {...}
local len = #components local len = #components
return function(_, e) return function(system, e)
local c local c
for i = 1, len do for i = 1, len do
c = components[i] c = components[i]
if type(c) == 'function' then if type(c) == 'function' then
if not c(_, e) then if not c(system, e) then
return false return false
end end
elseif e[c] == nil then elseif e[c] == nil then
@ -46,18 +108,18 @@ function tiny.requireAll(...)
end end
end end
--- Makes a Filter that filters Entities with specified Components. --- Makes a Filter that selects Entities with at least one of the specified
-- An Entity must have at least one specified Component to match the filter. -- Components and Filters.
-- @param ... List of Components -- @param ... List of required Components and other Filters.
function tiny.requireOne(...) function tiny.requireAny(...)
local components = {...} local components = {...}
local len = #components local len = #components
return function(_, e) return function(system, e)
local c local c
for i = 1, len do for i = 1, len do
c = components[i] c = components[i]
if type(c) == 'function' then if type(c) == 'function' then
if c(_, e) then if c(system, e) then
return true return true
end end
elseif e[c] ~= nil then elseif e[c] ~= nil then
@ -68,8 +130,89 @@ function tiny.requireOne(...)
end end
end end
--- Makes a Filter that rejects Entities with all specified Components and
-- Filters, and selects all other Entities.
-- @param ... List of required Components and other Filters.
function tiny.rejectAll(...)
local components = {...}
local len = #components
return function(system, e)
local c
for i = 1, len do
c = components[i]
if type(c) == 'function' then
if not c(system, e) then
return true
end
elseif e[c] == nil then
return true
end
end
return false
end
end
--- Makes a Filter that rejects Entities with at least one of the specified
-- Components and Filters, and selects all other Entities.
-- @param ... List of required Components and other Filters.
function tiny.rejectAny(...)
local components = {...}
local len = #components
return function(system, e)
local c
for i = 1, len do
c = components[i]
if type(c) == 'function' then
if c(system, e) then
return false
end
elseif e[c] ~= nil then
return false
end
end
return true
end
end
--- System functions. --- System functions.
-- A System is a wrapper around function callbacks for manipulating Entities. -- A System is a wrapper around function callbacks for manipulating Entities.
-- Systems are implemented as tables that contain at least one method;
-- an update function that takes parameters like so:
--
-- * `function system:update(dt)`.
--
-- There are also a few other optional callbacks:
--
-- * `function system:filter(entity)`
-- * `function system:onAdd(entity)`
-- * `function system:onRemove(entity)`
-- * `function system:onModify(dt)`
--
-- For Filters, it is convenient to use `tiny.requireAll` or `tiny.requireAny`,
-- but one can write their own filters as well. Set the Filter of a System like
-- so:
-- system.filter = tiny.requireAll("a", "b", "c")
-- or
-- function system:filter(entity)
-- return entity.myRequiredComponentName ~= nil
-- end
--
-- All Systems also have a few important fields that are initialized when the
-- system is added to the World. A few are important, and few should be less
-- commonly used.
--
-- * The `active` flag is whether or not the System is updated automatically.
-- Inactive Systems should be updated manually or not at all via
-- `system:update(dt)`. Defaults to true.
-- * The 'entities' field is an ordered list of Entities in the System. This
-- list can be used to quickly iterate through all Entities in a System.
-- * The `indices` field is a table of Entity keys to their indices in the
-- `entities` list. Most Systems can ignore this.
-- * The `modified` flag is an indicator if the System has been modified in
-- the last update. If so, the `onModify` callback will be called on the System
-- in the next update, if it has one. This is usually managed by tiny-ecs, so
-- users should mostly ignore this, too.
--
-- @section System -- @section System
-- Use an empty table as a key for identifying Systems. Any table that contains -- Use an empty table as a key for identifying Systems. Any table that contains
@ -81,34 +224,25 @@ local function isSystem(table)
return table[systemTableKey] return table[systemTableKey]
end end
--- Creates a System. Systems are tables that contain at least one field; --- Creates a default System.
-- an update function that takes parameters like so:
-- `function system:update(entities, dt)`. `entities` is an unordered table of
-- Entities with Entities as KEYS, and `dt` is the delta time. There are also a
-- few other optional callbacks:
-- `function system:filter(entity)` - returns a boolean,
-- `function system:onAdd(entity)` - returns nil,
-- `function system:onRemove(entity)` - returns nil.
-- For Filters, it is conveient to use `tiny.requireAll` or `tiny.requireOne`,
-- but one can write their own filters as well.
-- @param table A table to be used as a System, or `nil` to create a new System. -- @param table A table to be used as a System, or `nil` to create a new System.
-- @return A new System or System class
function tiny.system(table) function tiny.system(table)
if table == nil then table = table or {}
table = {}
end
table[systemTableKey] = true table[systemTableKey] = true
return table return table
end end
-- Update function for all Processing Systems. -- Update function for all Processing Systems.
local function processingSystemUpdate(system, entities, dt) local function processingSystemUpdate(system, dt)
local entities = system.entities
local preProcess = system.preProcess local preProcess = system.preProcess
local process = system.process local process = system.process
local postProcess = system.postProcess local postProcess = system.postProcess
local entity local entity
if preProcess then if preProcess then
preProcess(system, entities, dt) preProcess(system, dt)
end end
if process then if process then
@ -120,41 +254,88 @@ local function processingSystemUpdate(system, entities, dt)
end end
if postProcess then if postProcess then
postProcess(system, entities, dt) postProcess(system, dt)
end end
end end
--- Creates a Processing System. A Processing System iterates through its --- Creates a Processing System.
-- Entities in no particluar order, and updates them individually. It has two --
-- important fields, `function system:process(entity, dt)`, and `function -- A Processing System iterates through its Entities in no particluar order, and
-- system:filter(entity)`. `entities` is Entities, -- updates them individually. It has two important fields:
-- and `dt` is the delta time. There are also a few other --
-- optional callbacks: -- * `function system:process(entity, dt)`
-- `function system:preProcess(entities, dt)` - returns nil, -- * `function system:filter(entity)`
-- `function system:postProcess(entities, dt)` - returns nil, --
-- `function system:onAdd(entity)` - returns nil, -- There are also a few other optional callbacks, including the optional
-- `function system:onRemove(entity)` - returns nil. -- callbacks in `tiny.system`:
-- For Filters, it is conveient to use `tiny.requireAll` or `tiny.requireOne`, --
-- but one can write their own filters as well. -- * `function system:preProcess(entities, dt)`
-- @param table A table to be used as a System, or `nil` to create a new -- * `function system:postProcess(entities, dt)`
--
-- @param table A table to be used as a System, or `nil` to create a new
-- Processing System. -- Processing System.
-- @see system
-- @return A new Processing System or Processing System class
function tiny.processingSystem(table) function tiny.processingSystem(table)
if table == nil then table = table or {}
table = {}
end
table[systemTableKey] = true table[systemTableKey] = true
table.update = processingSystemUpdate table.update = processingSystemUpdate
return table return table
end end
-- Sorts Systems by a function system.sort(entity1, entity2) on modify.
local function sortedSystemOnModify(system, dt)
local entities = system.entities
local entityIndices = system.entityIndices
local sortDelegate = system.sortDelegate
if not sortDelegate then
local compare = system.compare
sortDelegate = function(e1, e2)
compare(system, e1, e2)
end
system.sortDelegate = sortDelegate
end
tsort(entities, sortDelegate)
for i = 1, #entities do
local entity = entities[i]
entityIndices[entity] = i
end
end
--- Creates a Sorted Processing System. A Sorted System iterates through its
-- Entities in a specific order, and updates them individually. It has three
-- important methods:
--
-- * `function system:process(entity, dt)`
-- * `function system:compare(entity1, entity2)`
-- * `function system:filter(entity)`
--
-- Sorted Systems have the same optitonal callbacks as ProcessingSystems.
-- @param table A table to be used as a System, or `nil` to create a new
-- Sorted System.
-- @see system
-- @see processingSystem
-- @return A new Sorted System or Sorted System class
function tiny.sortedSystem(table)
table = table or {}
table[systemTableKey] = true
table.update = processingSystemUpdate
table.onModify = sortedSystemOnModify
table.sort = sortedSystemOnModify
return table
end
--- World functions. --- World functions.
-- A World is a container that manages Entities and Systems. The tiny-ecs module -- A World is a container that manages Entities and Systems. Typically, a
-- is set to be the `__index` of all World tables, so the often clearer syntax of -- program uses one World at a time.
-- World:method can be used for any function in the library. For example, --
-- `tiny.add(world, e1, e2, e3)` is the same as `world:add(e1, e2, e3).` -- For all World functions except `tiny.world(...)`, object-oriented syntax can
-- be used instead of the documented syntax. For example,
-- `tiny.add(world, e1, e2, e3)` is the same as `world:add(e1, e2, e3)`.
-- @section World -- @section World
local worldMetaTable = { __index = tiny } -- Forward declaration
local worldMetaTable
--- Creates a new World. --- Creates a new World.
-- Can optionally add default Systems and Entities. -- Can optionally add default Systems and Entities.
@ -176,7 +357,7 @@ function tiny.world(...)
-- List of Entities to remove -- List of Entities to remove
systemsToRemove = {}, systemsToRemove = {},
-- Set of Entities -- Set of Entities
entities = {}, entities = {},
-- Number of Entities in World. -- Number of Entities in World.
@ -199,9 +380,8 @@ function tiny.world(...)
end end
--- Adds an Entity to the world. --- Adds an Entity to the world.
-- The new Entity will enter the world next time World:update is called. -- Also call this on Entities that have changed Components such that they
-- Also call this on Entities that have changed Components such that it -- match different Filters.
-- matches different systems.
-- @param world -- @param world
-- @param entity -- @param entity
function tiny.addEntity(world, entity) function tiny.addEntity(world, entity)
@ -214,7 +394,6 @@ end
tiny_addEntity = tiny.addEntity tiny_addEntity = tiny.addEntity
--- Adds a System to the world. --- Adds a System to the world.
-- The new System will enter the world next time World:update is called.
-- @param world -- @param world
-- @param system -- @param system
function tiny.addSystem(world, system) function tiny.addSystem(world, system)
@ -224,27 +403,26 @@ end
tiny_addSystem = tiny.addSystem tiny_addSystem = tiny.addSystem
--- Shortcut for adding multiple Entities and Systems to the World. --- Shortcut for adding multiple Entities and Systems to the World.
-- New objects will enter the World the next time World:update(dt) is called.
-- Also call this method when an Entity has had its Components changed, such
-- that it matches different Filters.
-- @param world -- @param world
-- @param ... Systems and Entities -- @param ... Systems and Entities
-- @see addEntity
-- @see addSystem
function tiny.add(world, ...) function tiny.add(world, ...)
local args = {...} local obj
for _, obj in ipairs(args) do for i = 1, select("#", ...) do
if isSystem(obj) then obj = select(i, ...)
tiny_addSystem(world, obj) if obj then
else -- Assume obj is an Entity if isSystem(obj) then
tiny_addEntity(world, obj) tiny_addSystem(world, obj)
else -- Assume obj is an Entity
tiny_addEntity(world, obj)
end
end end
end end
end end
tiny_add = tiny.add tiny_add = tiny.add
--- Removes an Entity to the World. --- Removes an Entity to the World.
-- The Entity will exit the World next time World:update is called.
-- Also call this on Entities that have changed Components such that it
-- matches different systems.
-- @param world -- @param world
-- @param entity -- @param entity
function tiny.removeEntity(world, entity) function tiny.removeEntity(world, entity)
@ -254,7 +432,6 @@ end
tiny_removeEntity = tiny.removeEntity tiny_removeEntity = tiny.removeEntity
--- Removes a System from the world. --- Removes a System from the world.
-- The System will exit the World next time World:update is called.
-- @param world -- @param world
-- @param system -- @param system
function tiny.removeSystem(world, system) function tiny.removeSystem(world, system)
@ -263,35 +440,28 @@ function tiny.removeSystem(world, system)
end end
tiny_removeSystem = tiny.removeSystem tiny_removeSystem = tiny.removeSystem
--- Shortcut for removing multiple Entities and Systems from the World. --- Shortcut for removing multiple Entities and Systems from the World.
-- Objects will exit the World the next time World:update(dt) is called.
-- @param world -- @param world
-- @param ... Systems and Entities -- @param ... Systems and Entities
-- @see removeEntity
-- @see removeSystem
function tiny.remove(world, ...) function tiny.remove(world, ...)
local args = {...} local obj
for _, obj in ipairs(args) do for i = 1, select("#", ...) do
if isSystem(obj) then obj = select(i, ...)
tiny_removeSystem(world, obj) if obj then
else -- Assume obj is an Entity if isSystem(obj) then
tiny_removeEntity(world, obj) tiny_removeSystem(world, obj)
else -- Assume obj is an Entity
tiny_removeEntity(world, obj)
end
end end
end end
end end
tiny_remove = tiny.remove tiny_remove = tiny.remove
--- Updates a System. -- Adds and removes Systems that have been marked from the World.
-- @param world function tiny_manageSystems(world)
-- @param system A System in the World to update
-- @param dt Delta time
function tiny.updateSystem(world, system, dt)
local es = world.systemEntities[system]
system:update(es, dt)
end
--- Adds and removes Systems that have been marked from the World.
-- The user of this library should seldom if ever call this.
-- @param world
function tiny.manageSystems(world)
local s2a, s2r = world.systemsToAdd, world.systemsToRemove local s2a, s2r = world.systemsToAdd, world.systemsToRemove
@ -303,18 +473,17 @@ function tiny.manageSystems(world)
local systemIndices = world.systemIndices local systemIndices = world.systemIndices
local entities = world.entities local entities = world.entities
local systems = world.systems local systems = world.systems
local system, index, filter
local system, systemData, index, filter, entityList, entityIndices, entityIndex, onRemove, onAdd local entityList, entityIndices, entityIndex, onRemove, onAdd
-- Remove Systems -- Remove Systems
for i = 1, #s2r do for i = 1, #s2r do
system = s2r[i] system = s2r[i]
index = systemIndices[system] index = systemIndices[system]
if index then if index then
systemData = systems[index]
onRemove = system.onRemove onRemove = system.onRemove
if onRemove then if onRemove then
entityList = systemData.entities entityList = system.entities
for j = 1, #entityList do for j = 1, #entityList do
onRemove(system, entityList[j]) onRemove(system, entityList[j])
end end
@ -322,7 +491,7 @@ function tiny.manageSystems(world)
systemIndices[system] = nil systemIndices[system] = nil
tremove(systems, index) tremove(systems, index)
for j = index, #systems do for j = index, #systems do
systemIndices[systems[j].system] = j systemIndices[systems[j]] = j
end end
end end
s2r[i] = nil s2r[i] = nil
@ -334,10 +503,13 @@ function tiny.manageSystems(world)
if not systemIndices[system] then if not systemIndices[system] then
entityList = {} entityList = {}
entityIndices = {} entityIndices = {}
systemData = { system = system, entities = entityList, indices = entityIndices, active = true } system.entities = entityList
system.indices = entityIndices
system.active = true
system.modified = true
index = #systems + 1 index = #systems + 1
systemIndices[system] = index systemIndices[system] = index
systems[index] = systemData systems[index] = system
-- Try to add Entities -- Try to add Entities
onAdd = system.onAdd onAdd = system.onAdd
@ -359,12 +531,9 @@ function tiny.manageSystems(world)
end end
end end
tiny_manageSystems = tiny.manageSystems
--- Adds and removes Entities that have been marked. -- Adds and removes Entities that have been marked.
-- The user of this library should seldom if ever call this. function tiny_manageEntities(world)
-- @param world
function tiny.manageEntities(world)
local e2a, e2r = world.entitiesToAdd, world.entitiesToRemove local e2a, e2r = world.entitiesToAdd, world.entitiesToRemove
@ -376,7 +545,8 @@ function tiny.manageEntities(world)
local entities = world.entities local entities = world.entities
local systems = world.systems local systems = world.systems
local entityCount = world.entityCount local entityCount = world.entityCount
local entity, system, systemData, index, onRemove, onAdd, ses, seis, filter, tmpEntity local entity, system, index
local onRemove, onAdd, ses, seis, filter, tmpEntity
-- Remove Entities -- Remove Entities
for i = 1, #e2r do for i = 1, #e2r do
@ -385,13 +555,13 @@ function tiny.manageEntities(world)
entities[entity] = nil entities[entity] = nil
for j = 1, #systems do for j = 1, #systems do
systemData = systems[j] system = systems[j]
system = systemData.system ses = system.entities
ses = systemData.entities seis = system.indices
seis = systemData.indices
index = seis[entity] index = seis[entity]
if index then if index then
system.modified = true
tmpEntity = ses[#ses] tmpEntity = ses[#ses]
ses[index] = tmpEntity ses[index] = tmpEntity
seis[tmpEntity] = index seis[tmpEntity] = index
@ -418,12 +588,12 @@ function tiny.manageEntities(world)
entities[entity] = true entities[entity] = true
for j = 1, #systems do for j = 1, #systems do
systemData = systems[j] system = systems[j]
system = systemData.system ses = system.entities
ses = systemData.entities seis = system.indices
seis = systemData.indices
filter = system.filter filter = system.filter
if filter and filter(system, entity) then if filter and filter(system, entity) then
system.modified = true
index = #ses + 1 index = #ses + 1
ses[index] = entity ses[index] = entity
seis[entity] = index seis[entity] = index
@ -444,11 +614,9 @@ function tiny.manageEntities(world)
world.entityCount = entityCount world.entityCount = entityCount
end end
tiny_manageEntities = tiny.manageEntities
--- Updates the World. --- Updates the World.
-- Frees Entities that have been marked for freeing, adds -- Put this in your main loop.
-- entities that have been marked for adding, etc.
-- @param world -- @param world
-- @param dt Delta time -- @param dt Delta time
function tiny.update(world, dt) function tiny.update(world, dt)
@ -457,20 +625,31 @@ function tiny.update(world, dt)
tiny_manageEntities(world) tiny_manageEntities(world)
local systems = world.systems local systems = world.systems
local systemData local system, update, onModify, entities
-- Iterate through Systems IN ORDER -- Iterate through Systems IN ORDER
for i = 1, #systems do for i = 1, #systems do
systemData = systems[i] system = systems[i]
if systemData.active then if system.active then
systemData.system:update(systemData.entities, dt)
-- Call the modify callback on Systems that have been modified.
onModify = system.onModify
if onModify and system.modified then
onModify(system, dt)
end
--Update Systems that have an update method (most Systems)
update = system.update
if update then
update(system, dt)
end
system.modified = false
end end
end end
end end
--- Removes all Entities from the World. --- Removes all Entities from the World.
-- When World:update(dt) is next called,
-- all Entities will be removed.
-- @param world -- @param world
function tiny.clearEntities(world) function tiny.clearEntities(world)
for e in pairs(world.entities) do for e in pairs(world.entities) do
@ -479,80 +658,76 @@ function tiny.clearEntities(world)
end end
--- Removes all Systems from the World. --- Removes all Systems from the World.
-- When World:update(dt) is next called,
-- all Systems will be removed.
-- @param world -- @param world
function tiny.clearSystems(world) function tiny.clearSystems(world)
local systems = world.systems local systems = world.systems
for i = #systems, 1, -1 do for i = #systems, 1, -1 do
tiny_removeSystem(world, systems[i].system) tiny_removeSystem(world, systems[i])
end end
end end
--- Gets count of Entities in World. --- Gets number of Entities in the World.
-- @param world -- @param world
-- @return An integer
function tiny.getEntityCount(world) function tiny.getEntityCount(world)
return world.entityCount return world.entityCount
end end
--- Gets count of Systems in World. --- Gets number of Systems in World.
-- @param world -- @param world
-- @return An integer
function tiny.getSystemCount(world) function tiny.getSystemCount(world)
return #(world.systems) return #(world.systems)
end end
--- Gets the index of a System in the world. Lower indexed Systems are processed --- Gets the index of a System in the World. Lower indexed Systems are processed
-- before higher indexed systems. -- before higher indexed systems.
-- @param world -- @param world
-- @param system -- @param system
-- @return An integer between 1 and world:getSystemCount() inclusive
function tiny.getSystemIndex(world, system) function tiny.getSystemIndex(world, system)
return world.systemIndices[system] return world.systemIndices[system]
end end
--- Sets the index of a System in the world. Changes the order in --- Sets the index of a System in the World. Changes the order in
-- which they Systems processed, because lower indexed Systems are processed -- which they Systems processed, because lower indexed Systems are processed
-- first. -- first.
-- @param world -- @param world
-- @param system -- @param system
-- @param index -- @param index
-- @return Old index
function tiny.setSystemIndex(world, system, index) function tiny.setSystemIndex(world, system, index)
local systemIndices = world.systemIndices local systemIndices = world.systemIndices
local oldIndex = systemIndices[system] local oldIndex = systemIndices[system]
local systems = world.systems local systems = world.systems
local systemData = systems[oldIndex] local system = systems[oldIndex]
tremove(systems, oldIndex) tremove(systems, oldIndex)
tinsert(systems, index, systemData) tinsert(systems, index, system)
for i = oldIndex, index, index >= oldIndex and 1 or -1 do for i = oldIndex, index, index >= oldIndex and 1 or -1 do
systemIndices[systems[i].system] = i systemIndices[systems[i]] = i
end end
return oldIndex
end end
--- Activates Systems in the World. -- Construct world metatable.
-- Activated Systems will be update whenever tiny.update(world, dt) is called. worldMetaTable = {
-- @param world __index = {
-- @param ... Systems to activate. The Systems must already be added to the add = tiny.add,
-- World. addEntity = tiny.addEntity,
function tiny.activate(world, ...) addSystem = tiny.addSystem,
local args = {...} remove = tiny.remove,
for _, system in ipairs(args) do removeEntity = tiny.removeEntity,
world.systems[world.systemIndices[system]].active = true update = tiny.update,
end clearEntities = tiny.clearEntities,
end clearSystems = tiny.clearSystems,
getEntityCount = tiny.getEntityCount,
--- Deactivates Systems in the World. getSystemCount = tiny.getSystemCount,
-- Deactivated Systems must be update manually, and will not update when the getSystemIndex = tiny.getSystemIndex,
-- rest of World updates. They will, however, process new Entities added while setSystemIndex = tiny.setSystemIndex
-- the System is deactivated. }
-- @param world }
-- @param ... Systems to deactivate. The Systems must already be added to the
-- World.
function tiny.deactivate(world, ...)
local args = {...}
for _, system in ipairs(args) do
world.systems[world.systemIndices[system]].active = false
end
end
return tiny return tiny

View File

@ -6,7 +6,7 @@ function MainHud:drawHud(dt)
local n = self.levelState.totalEnemiesToKill - self.levelState.enemiesKilled local n = self.levelState.totalEnemiesToKill - self.levelState.enemiesKilled
local d = self.levelState.totalEnemiesToKill local d = self.levelState.totalEnemiesToKill
love.graphics.setFont(assets.fnt_hud) love.graphics.setFont(assets.fnt_hud)
love.graphics.printf("Wave " .. self.levelState.wave, 20, 20, 300, "left") love.graphics.printf("Wave " .. self.levelState.wave, 20, 20, 300, "left")
love.graphics.setFont(assets.fnt_smallhud) love.graphics.setFont(assets.fnt_smallhud)
love.graphics.printf(n .. "/" .. d .. " Pigs Remaining", 20, 60, 500, "left") love.graphics.printf(n .. "/" .. d .. " Pigs Remaining", 20, 60, 500, "left")
love.graphics.printf("Total Pigs Killed: " .. self.levelState.score, love.graphics.getWidth() - 420, 20, 400, "right") love.graphics.printf("Total Pigs Killed: " .. self.levelState.score, love.graphics.getWidth() - 420, 20, 400, "right")

View File

@ -26,8 +26,8 @@ function Intro:load()
require ("src.systems.TileMapRenderSystem")(camera, tileMap), require ("src.systems.TileMapRenderSystem")(camera, tileMap),
require ("src.systems.SpriteSystem")(camera, "bg"), require ("src.systems.SpriteSystem")(camera, "bg"),
require ("src.systems.SpriteSystem")(camera, "fg"), require ("src.systems.SpriteSystem")(camera, "fg"),
require ("src.systems.HudSystem")(self, "hudBg"), require ("src.systems.HudSystem")("hudBg"),
require ("src.systems.HudSystem")(self, "hudFg"), require ("src.systems.HudSystem")("hudFg"),
TransitionScreen(), TransitionScreen(),
ScreenSplash(0.5, 0.2, "Cammando Kibbles"), ScreenSplash(0.5, 0.2, "Cammando Kibbles"),
ScreenSplash(0, 0, "Created by bakpakin for Ludum Dare 32", 300, assets.fnt_reallysmallhud, "left", 20, 20), ScreenSplash(0, 0, "Created by bakpakin for Ludum Dare 32", 300, assets.fnt_reallysmallhud, "left", 20, 20),
@ -41,8 +41,8 @@ end
function Intro:update(dt) function Intro:update(dt)
self.time = self.time + dt self.time = self.time + dt
if love.keyboard.isDown(" ") and self.time > 0.55 then if love.keyboard.isDown(" ") and self.time > 0.55 then
world:add(TransitionScreen(true, Level("assets/lvl1"))) world:add(TransitionScreen(true, Level("assets/lvl1")))
end end
end end
function Intro:draw() function Intro:draw()

View File

@ -63,8 +63,8 @@ function Level:load()
require ("src.systems.SpriteSystem")(camera, "bg"), require ("src.systems.SpriteSystem")(camera, "bg"),
require ("src.systems.SpriteSystem")(camera, "fg"), require ("src.systems.SpriteSystem")(camera, "fg"),
require ("src.systems.LifetimeSystem")(), require ("src.systems.LifetimeSystem")(),
require ("src.systems.HudSystem")(self, "hudBg"), require ("src.systems.HudSystem")("hudBg"),
require ("src.systems.HudSystem")(self, "hudFg"), require ("src.systems.HudSystem")("hudFg"),
require ("src.systems.WaveSystem")(self), require ("src.systems.WaveSystem")(self),
require ("src.systems.SpawnSystem")(self), require ("src.systems.SpawnSystem")(self),
require ("src.entities.MainHud")(self), require ("src.entities.MainHud")(self),

View File

@ -4,7 +4,7 @@ function DrawBackgroundSystem:init(r, g, b)
self.r, self.g, self.b = r, g, b self.r, self.g, self.b = r, g, b
end end
function DrawBackgroundSystem:update(entities, dt) function DrawBackgroundSystem:update(dt)
local r1, g1, b1, a = love.graphics.getColor() local r1, g1, b1, a = love.graphics.getColor()
love.graphics.setColor(self.r, self.g, self.b, 255) love.graphics.setColor(self.r, self.g, self.b, 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())

View File

@ -1,12 +1,11 @@
local HudSystem = tiny.processingSystem(class "HudSystem") local HudSystem = tiny.processingSystem(class "HudSystem")
function HudSystem:init(levelState, layerFlag) function HudSystem:init(layerFlag)
self.levelState = levelState
self.filter = tiny.requireAll("drawHud", layerFlag) self.filter = tiny.requireAll("drawHud", layerFlag)
end end
function HudSystem:process(e, dt) function HudSystem:process(e, dt)
e:drawHud(dt) e:drawHud(dt)
end end
return HudSystem return HudSystem

View File

@ -9,7 +9,7 @@ function SpawnSystem:init(levelState)
self.time = 0 self.time = 0
end end
function SpawnSystem:update(entities, dt) function SpawnSystem:update(dt)
self.time = self.time + dt self.time = self.time + dt
local levelState = self.levelState local levelState = self.levelState
if levelState.isSpawning and levelState.enemiesSpawned < levelState.totalEnemiesToKill and self.time >= levelState.spawnInterval then if levelState.isSpawning and levelState.enemiesSpawned < levelState.totalEnemiesToKill and self.time >= levelState.spawnInterval then

View File

@ -5,11 +5,11 @@ function SpriteSystem:init(camera, layerFlag)
self.filter = tiny.requireAll("sprite", "pos", layerFlag) self.filter = tiny.requireAll("sprite", "pos", layerFlag)
end end
function SpriteSystem:preProcess(entities, dt) function SpriteSystem:preProcess(dt)
self.camera:apply() self.camera:apply()
end end
function SpriteSystem:postProcess(entities, dt) function SpriteSystem:postProcess(dt)
self.camera:remove() self.camera:remove()
love.graphics.setColor(255, 255, 255, 255) love.graphics.setColor(255, 255, 255, 255)
end end

View File

@ -9,7 +9,7 @@ function TileMapRenderSystem:init(camera, tileMap)
end end
end end
function TileMapRenderSystem:update(entities, dt) function TileMapRenderSystem:update(dt)
self.camera:draw(self.drawFn) self.camera:draw(self.drawFn)
end end

View File

@ -2,7 +2,7 @@ local TimerEvent = require "src.entities.TimerEvent"
local WaveSystem = tiny.system(class "WaveSystem") local WaveSystem = tiny.system(class "WaveSystem")
WaveSystem.filter = tiny.requireOne("isEnemy") WaveSystem.filter = tiny.requireAll("isEnemy")
function WaveSystem:init(levelState) function WaveSystem:init(levelState)
self.levelState = levelState self.levelState = levelState
@ -22,6 +22,4 @@ function WaveSystem:onRemove(e)
end end
end end
function WaveSystem:update(entities, dt) end
return WaveSystem return WaveSystem