19 Commits

Author SHA1 Message Date
Calvin Rose
821914795d Merge pull request #25 from yangruihan/master
fix README.md example error
2020-11-03 07:18:04 -06:00
C.y
2beca9a0ad fix README.md example error 2020-11-03 19:35:44 +08:00
Calvin Rose
afd7d326d7 Fix #22 - manage systems before setSystemIndex 2020-08-12 08:28:57 -05:00
Calvin Rose
e095e10d44 Merge pull request #21 from RantingBob/patch-1
Fixed nil entitylist in nocache system
2020-02-23 21:21:05 -06:00
Bob Gardner
3c4b3a7f68 Fixed nil entitylist in nocache system
Systems that set nocache to true would fail as the entity list was set to system.world.entityList but should have been system.world.entities.
2020-02-23 16:45:01 -08:00
Calvin Rose
0f17f116ab Update .travis.yml 2019-10-13 00:14:12 -05:00
Calvin Rose
584be2c952 Merge pull request #20 from firoxer/patch-1 2019-10-13 01:09:55 -04:00
Oliver Vartiainen
36364df4e6 Fix a few spellings in the README
Hi! While reading the README I noticed a few things that could be corrected. Here they are. Thanks for the project, it's very interesting!
2019-10-12 22:02:37 +03:00
Calvin Rose
65de2a9c6f Merge pull request #19 from wqferr/fix-init-lua
Fix init.lua
2019-07-23 08:40:27 -05:00
William Ferreira
4631216c27 Fix init.lua 2019-07-23 00:40:11 -03:00
Calvin Rose
7c7de1db0c Update README.md 2019-01-23 16:57:20 -05:00
bakpakin
fe7e2854de Update doc. 2016-08-10 21:48:20 -04:00
bakpakin
311943e070 Fix doc bug. 2016-08-10 21:42:18 -04:00
bakpakin
8a3c22e74f Add new rockspec. 2016-08-10 19:45:58 -04:00
bakpakin
a0fa0904f6 Update filer documentation to be more explicit. 2016-08-10 19:36:20 -04:00
Calvin Rose
80bb6b8d31 Remove world.entityCount and world.entityList. 2016-08-10 17:23:48 -04:00
bakpakin
83d806011b Combine the 'add entities' procedure in manage_entities with 'change
entities'
2016-08-10 07:23:05 -04:00
Calvin Rose
d720d361e6 Remove redundant non-nil check 2016-07-13 09:43:36 -04:00
Calvin Rose
d94b178670 Make source pass luacheck. Remove tiny.getSystemIndex(). 2016-07-05 17:15:18 -04:00
7 changed files with 132 additions and 134 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
language: erlang
language: c
env:
global:
- LUAROCKS_BASE=luarocks-2.2.2
- LUAROCKS_BASE=luarocks-3.2.1
matrix:
- LUA=lua5.1 LUA_DEV=liblua5.1-dev LUA_VER=5.1 LUA_SFX=5.1 LUA_INCDIR=/usr/include/lua5.1
- LUA=lua5.2 LUA_DEV=liblua5.2-dev LUA_VER=5.2 LUA_SFX=5.2 LUA_INCDIR=/usr/include/lua5.2
+14 -7
View File
@@ -1,5 +1,12 @@
# tiny-ecs #
## NOTE
Although there have been almost no commits in several years, this
project is not abandoned. tiny-ecs is, for most intents and
purposes, finished, and no bugs have been brought to my attention in a while.
New issues on GitHub will be addressed.
[![Build Status](https://travis-ci.org/bakpakin/tiny-ecs.png?branch=master)](https://travis-ci.org/bakpakin/tiny-ecs)[![License](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](LICENSE)
Tiny-ecs is an Entity Component System for Lua that's simple, flexible, and useful.
@@ -8,11 +15,11 @@ for simulating large and complex systems. For more explanation on Entity
Component Systems, here is some
[basic info](http://en.wikipedia.org/wiki/Entity_component_system "Wikipedia").
Tiny-ecs also works well with objected oriented programming in Lua because
Tiny-ecs also works well with object-oriented programming in Lua because
Systems and Entities do not use metatables. This means you can subclass your
Systems and Entities, and use existing Lua class frameworks with tiny-ecs, no problem.
Systems and Entities and use existing Lua class frameworks with tiny-ecs, no problem.
For an example on how to use tiny-ecs with object-oriented Lua, take a look at the
demo branch, specifically the systems and entities sub-directories.
demo branch, specifically the systems and entities subdirectories.
## Overview ##
Tiny-ecs has four important types: Worlds, Filters, Systems, and Entities.
@@ -21,7 +28,7 @@ take an Entity as a parameter.
### Entities ###
Entities are simply Lua tables of data that gets processed by Systems. Entities
should contain primarily data rather than code, as it is the Systems's job to
should contain primarily data rather than code, as it is the System's job to
do logic on data. Henceforth, a key-value pair in an Entity will
be referred to as a Component.
@@ -49,7 +56,7 @@ local talkingSystem = tiny.processingSystem()
talkingSystem.filter = tiny.requireAll("name", "mass", "phrase")
function talkingSystem:process(e, dt)
e.mass = e.mass + dt * 3
print(("%s who weighs %d pounds, says %q."):format(e.name, e.mass, e.phrase)
print(("%s who weighs %d pounds, says %q."):format(e.name, e.mass, e.phrase))
end
local joe = {
@@ -68,10 +75,10 @@ end
## Use It ##
Copy paste tiny.lua into your source folder. For stability and consistent API,
please use a tagged release or use luarocks.
please use a tagged release or use LuaRocks.
## Luarocks ##
Tiny-ecs is also on [Luarocks](https://luarocks.org/) and can be installed with
Tiny-ecs is also on [LuaRocks](https://luarocks.org/) and can be installed with
`luarocks install tiny-ecs`.
## Demo ##
+3 -2
View File
@@ -1,5 +1,6 @@
-- Helper Lua file for easy require if tiny-ecs is used as a git submodule or
-- folder. Not needed in many cases, including luarocks distribution.
local directory = (...):match("(.-)[^%.]+$")
return require(directory .. 'tiny')
local args = {...}
local directory = args[1]
return require(directory .. '.tiny')
+24
View File
@@ -0,0 +1,24 @@
package = "tiny-ecs"
version = "1.3-3"
source = {
url = "git://github.com/bakpakin/tiny-ecs",
tag = version
}
description = {
summary = "Entity Component System for Lua.",
detailed = [[
Pure Lua implementation of an easy to use, compact, fast, and flexible
Entity Component System. Works well with Object Orientation.
]],
homepage = "https://github.com/bakpakin/tiny-ecs",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
tiny = "tiny.lua"
}
}
+10
View File
@@ -310,4 +310,14 @@ describe('tiny-ecs:', function()
assert.are.same(_G, GLOBALS)
end)
it("Can set system indices", function()
local world = tiny.world()
local systemA = tiny.system()
local systemB = tiny.system()
world:addSystem(systemA)
world:addSystem(systemB)
world:setSystemIndex(systemA, 1)
assert(true)
end)
end)
+8
View File
@@ -0,0 +1,8 @@
local tiny = require('tiny')
local world = tiny.world()
local systemA = tiny.system()
local systemB = tiny.system()
world:addSystem(systemA)
world:addSystem(systemB)
world:setSystemIndex(systemA, 1)
+71 -123
View File
@@ -41,12 +41,13 @@ local tiny_addSystem
local tiny_add
local tiny_removeEntity
local tiny_removeSystem
local tiny_remove
--- Filter functions.
-- 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.
-- value indicating if the Entity should be processed by the System. A truthy
-- value includes the entity, while a falsey (nil or false) value excludes the
-- entity.
--
-- Filters must be added to Systems by setting the `filter` field of the System.
-- Filter's returned by tiny-ecs's Filter functions are immutable and can be
@@ -229,7 +230,7 @@ end
-- removed from the world, after all Entities are removed from the System.
-- * `function system:preWrap(dt)` - Called on each system before update is
-- called on any system.
-- * `function system:postWrap(dt) - Called on each system in reverse order
-- * `function system:postWrap(dt)` - Called on each system in reverse order
-- after update is called on each system. The idea behind `preWrap` and
-- `postWrap` is to allow for systems that modify the behavior of other systems.
-- Say there is a DrawingSystem, which draws sprites to the screen, and a
@@ -277,11 +278,13 @@ end
--
-- There is another option to (hopefully) increase performance in systems that
-- have items added to or removed from them often, and have lots of entities in
-- them. Setting the `nocache' field of the system might improve performance.
-- them. Setting the `nocache` field of the system might improve performance.
-- It is still experimental. There are some restriction to systems without
-- caching, however. * There is no `entities` table. * Callbacks such onAdd,
-- onRemove, and onModify will never be called * Noncached systems cannot be
-- sorted (There is no entities list to sort).
-- caching, however.
--
-- * There is no `entities` table.
-- * Callbacks such onAdd, onRemove, and onModify will never be called
-- * Noncached systems cannot be sorted (There is no entities list to sort).
--
-- @section System
@@ -306,7 +309,7 @@ local function processingSystemUpdate(system, dt)
if process then
if system.nocache then
local entities = system.world.entityList
local entities = system.world.entities
local filter = system.filter
if filter then
for i = 1, #entities do
@@ -330,7 +333,7 @@ local function processingSystemUpdate(system, dt)
end
-- Sorts Systems by a function system.sortDelegate(entity1, entity2) on modify.
local function sortedSystemOnModify(system, dt)
local function sortedSystemOnModify(system)
local entities = system.entities
local indices = system.indices
local sortDelegate = system.sortDelegate
@@ -420,9 +423,6 @@ local worldMetaTable
function tiny.world(...)
local ret = setmetatable({
-- List of Entities to add
entitiesToAdd = {},
-- List of Entities to remove
entitiesToRemove = {},
@@ -438,14 +438,9 @@ function tiny.world(...)
-- Set of Entities
entities = {},
-- List of Entities
entityList = {},
-- Number of Entities in World
entityCount = 0,
-- List of Systems
systems = {}
}, worldMetaTable)
tiny_add(ret, ...)
@@ -459,13 +454,8 @@ end
-- Also call this on Entities that have changed Components such that they
-- match different Filters. Returns the Entity.
function tiny.addEntity(world, entity)
if world.entities[entity] then
local e2c = world.entitiesToChange
e2c[#e2c + 1] = entity
else
local e2a = world.entitiesToAdd
e2a[#e2a + 1] = entity
end
local e2c = world.entitiesToChange
e2c[#e2c + 1] = entity
return entity
end
tiny_addEntity = tiny.addEntity
@@ -497,7 +487,7 @@ function tiny.add(world, ...)
end
tiny_add = tiny.add
--- Removes an Entity to the World. Returns the Entity.
--- Removes an Entity from the World. Returns the Entity.
function tiny.removeEntity(world, entity)
local e2r = world.entitiesToRemove
e2r[#e2r + 1] = entity
@@ -529,7 +519,6 @@ function tiny.remove(world, ...)
end
return ...
end
tiny_remove = tiny.remove
-- Adds and removes Systems that have been marked from the World.
function tiny_manageSystems(world)
@@ -543,7 +532,7 @@ function tiny_manageSystems(world)
world.systemsToAdd = {}
world.systemsToRemove = {}
local worldEntityList = world.entityList
local worldEntityList = world.entities
local systems = world.systems
-- Remove Systems
@@ -623,58 +612,58 @@ end
-- Adds, removes, and changes Entities that have been marked.
function tiny_manageEntities(world)
local e2a = world.entitiesToAdd
local e2r = world.entitiesToRemove
local e2c = world.entitiesToChange
-- Early exit
if #e2a == 0 and #e2r == 0 and #e2c == 0 then
if #e2r == 0 and #e2c == 0 then
return
end
world.entitiesToChange = {}
world.entitiesToAdd = {}
world.entitiesToRemove = {}
local entities = world.entities
local entityList = world.entityList
local systems = world.systems
local entityCount = world.entityCount
-- Change Entities
for i = 1, #e2c do
local entity = e2c[i]
if entities[entity] then
for j = 1, #systems do
local system = systems[j]
if not system.nocache then
local ses = system.entities
local seis = system.indices
local index = seis[entity]
local filter = system.filter
if filter and filter(system, entity) then
if not index then
system.modified = true
index = #ses + 1
ses[index] = entity
seis[entity] = index
local onAdd = system.onAdd
if onAdd then
onAdd(system, entity)
end
end
elseif index then
-- Add if needed
if not entities[entity] then
local index = #entities + 1
entities[entity] = index
entities[index] = entity
end
for j = 1, #systems do
local system = systems[j]
if not system.nocache then
local ses = system.entities
local seis = system.indices
local index = seis[entity]
local filter = system.filter
if filter and filter(system, entity) then
if not index then
system.modified = true
local tmpEntity = ses[#ses]
ses[index] = tmpEntity
seis[tmpEntity] = index
seis[entity] = nil
ses[#ses] = nil
local onRemove = system.onRemove
if onRemove then
onRemove(system, entity)
index = #ses + 1
ses[index] = entity
seis[entity] = index
local onAdd = system.onAdd
if onAdd then
onAdd(system, entity)
end
end
elseif index then
system.modified = true
local tmpEntity = ses[#ses]
ses[index] = tmpEntity
seis[tmpEntity] = index
seis[entity] = nil
ses[#ses] = nil
local onRemove = system.onRemove
if onRemove then
onRemove(system, entity)
end
end
end
end
@@ -688,12 +677,11 @@ function tiny_manageEntities(world)
local listIndex = entities[entity]
if listIndex then
-- Remove Entity from world state
local lastEntity = entityList[#entityList]
local lastEntity = entities[#entities]
entities[lastEntity] = listIndex
entities[entity] = nil
entityList[listIndex] = lastEntity
entityList[#entityList] = nil
entityCount = entityCount - 1
entities[listIndex] = lastEntity
entities[#entities] = nil
-- Remove from cached systems
for j = 1, #systems do
local system = systems[j]
@@ -717,39 +705,6 @@ function tiny_manageEntities(world)
end
end
end
-- Add Entities
for i = 1, #e2a do
local entity = e2a[i]
if not entities[entity] then
local listIndex = #entityList + 1
entities[entity] = listIndex
entityList[listIndex] = entity
entityCount = entityCount + 1
for j = 1, #systems do
local system = systems[j]
if not system.nocache then
local ses = system.entities
local seis = system.indices
local filter = system.filter
if filter and filter(system, entity) then
system.modified = true
local index = #ses + 1
ses[index] = entity
seis[entity] = index
local onAdd = system.onAdd
if onAdd then
onAdd(system, entity)
end
end
end
end
end
e2a[i] = nil
end
-- Update Entity count
world.entityCount = entityCount
end
--- Manages Entities and Systems marked for deletion or addition. Call this
@@ -759,7 +714,7 @@ function tiny.refresh(world)
tiny_manageSystems(world)
tiny_manageEntities(world)
local systems = world.systems
for i = 1, #systems do
for i = #systems, 1, -1 do
local system = systems[i]
if system.active then
local onModify = system.onModify
@@ -785,10 +740,17 @@ function tiny.update(world, dt, filter)
-- Iterate through Systems IN REVERSE ORDER
for i = #systems, 1, -1 do
local system = systems[i]
local preWrap = system.preWrap
if preWrap and system.active and
((not filter) or filter(world, system)) then
preWrap(system, dt)
if system.active then
-- Call the modify callback on Systems that have been modified.
local onModify = system.onModify
if onModify and system.modified then
onModify(system, dt)
end
local preWrap = system.preWrap
if preWrap and
((not filter) or filter(world, system)) then
preWrap(system, dt)
end
end
end
@@ -797,12 +759,6 @@ function tiny.update(world, dt, filter)
local system = systems[i]
if system.active and ((not filter) or filter(world, system)) then
-- Call the modify callback on Systems that have been modified.
local onModify = system.onModify
if onModify and system.modified then
onModify(system, dt)
end
-- Update Systems that have an update method (most Systems)
local update = system.update
if update then
@@ -811,9 +767,7 @@ function tiny.update(world, dt, filter)
local bufferedTime = (system.bufferedTime or 0) + dt
while bufferedTime >= interval do
bufferedTime = bufferedTime - interval
if update then
update(system, interval)
end
update(system, interval)
end
system.bufferedTime = bufferedTime
else
@@ -839,7 +793,7 @@ end
--- Removes all Entities from the World.
function tiny.clearEntities(world)
local el = world.entityList
local el = world.entities
for i = 1, #el do
tiny_removeEntity(world, el[i])
end
@@ -855,24 +809,19 @@ end
--- Gets number of Entities in the World.
function tiny.getEntityCount(world)
return world.entityCount
return #world.entities
end
--- Gets number of Systems in World.
function tiny.getSystemCount(world)
return #(world.systems)
end
--- Gets the index of the System in the World.
-- A simpler alternative is `system.index`.
function tiny.getSystemIndex(world, system)
return system.index
return #world.systems
end
--- Sets the index of a System in the World, and returns the old index. Changes
-- the order in which they Systems processed, because lower indexed Systems are
-- processed first. Returns the old system.index.
function tiny.setSystemIndex(world, system, index)
tiny_manageSystems(world)
local oldIndex = system.index
local systems = world.systems
@@ -905,10 +854,9 @@ worldMetaTable = {
clearSystems = tiny.clearSystems,
getEntityCount = tiny.getEntityCount,
getSystemCount = tiny.getSystemCount,
getSystemIndex = tiny.getSystemIndex,
setSystemIndex = tiny.setSystemIndex
},
__tostring = function(self)
__tostring = function()
return "<tiny-ecs_World>"
end
}