Skip to content

Commit d9ea93f

Browse files
committed
Improved documentation, pipeline correction
1 parent 87f0ae9 commit d9ea93f

26 files changed

+3920
-989
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
language: python
2-
sudo: false
32

43
env:
54
- LUA="lua=5.1"

ECS.lua

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

ECS_concat.lua

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--[[
2-
ECS Lua v2.1.0 [2021-10-15 11:00]
2+
ECS Lua v2.1.1
33
44
ECS Lua is a fast and easy to use ECS (Entity Component System) engine for game development.
55
@@ -2118,9 +2118,17 @@ __F__["System"] = function()
21182118
error("The step parameter must one of ", table.concat(STEPS, ", "))
21192119
end
21202120

2121-
if type(order) == "function" then
2121+
if (order and type(order) == "function") then
21222122
updateFn = order
21232123
order = nil
2124+
elseif query and type(query) == "function" then
2125+
updateFn = query
2126+
query = nil
2127+
end
2128+
2129+
if (order and type(order) == "table" and (order.isQuery or order.isQueryBuilder)) then
2130+
query = order
2131+
order = nil
21242132
end
21252133

21262134
if (order == nil or order < 0) then
@@ -2785,7 +2793,7 @@ __F__["Timer"] = function()
27852793
self.Time.DeltaFixed = 1000/frequency/1000
27862794
end
27872795

2788-
function Timer:Update(now, step, callback)
2796+
function Timer:Update(now, step, beforeUpdate, update)
27892797
if (self.FirstUpdate == 0) then
27902798
self.FirstUpdate = now
27912799
end
@@ -2834,12 +2842,14 @@ __F__["Timer"] = function()
28342842
local nLoops = 0
28352843
local updated = false
28362844

2845+
beforeUpdate(Time)
2846+
28372847
-- Fixed time is updated in regular intervals (equal to DeltaFixed) until time property is reached.
28382848
while (Time.Process <= Time.Frame and nLoops < MAX_SKIP_FRAMES) do
28392849

28402850
updated = true
28412851

2842-
callback(Time)
2852+
update(Time)
28432853

28442854
nLoops = nLoops + 1
28452855
Time.Process = Time.Process + Time.DeltaFixed
@@ -2857,7 +2867,8 @@ __F__["Timer"] = function()
28572867
Time.Interpolation = 1
28582868
end
28592869

2860-
callback(Time)
2870+
beforeUpdate(Time)
2871+
update(Time)
28612872

28622873
if step == "render" then
28632874
-- last step, save last frame time
@@ -3187,66 +3198,71 @@ __F__["World"] = function()
31873198
| | |
31883199
'-------------------------------------'
31893200
]]
3190-
3191-
self._timer:Update(now, step, function(Time)
3192-
if step == "process" then
3193-
self._executor:ScheduleTasks(Time)
3194-
self._executor:ExecProcess(Time)
3195-
elseif step == "transform" then
3196-
self._executor:ExecTransform(Time)
3197-
else
3198-
self._executor:ExecRender(Time)
3199-
end
32003201

3201-
-- 60FPS = ((1000/60/1000)*0.7)/3 = 0.0038888888888888883
3202-
-- 30FPS = ((1000/30/1000)*0.7)/3 = 0.007777777777777777
3203-
local maxScheduleExecTime = (Time.DeltaFixed * (self.maxScheduleExecTimePercent or 0.7))/3
3204-
3205-
-- run suspended Tasks
3206-
self._executor:ExecTasks(maxScheduleExecTime)
3207-
3208-
-- cleans up after running scripts
3209-
while self._dirty do
3210-
self._dirty = false
3211-
3212-
-- 1: remove entities
3213-
local entitiesRemoved = {}
3214-
for entity,_ in pairs(self._entitiesRemoved) do
3215-
entitiesRemoved[entity] = self._entitiesUpdated[entity]
3216-
self._entitiesUpdated[entity] = nil
3202+
self._timer:Update(
3203+
now, step,
3204+
function(Time)
3205+
if step == "process" then
3206+
self._executor:ScheduleTasks(Time)
32173207
end
3218-
self._entitiesRemoved = {}
3219-
self._executor:ExecOnRemove(Time, entitiesRemoved)
3220-
entitiesRemoved = nil
3221-
3222-
local changed = {}
3223-
local hasChange = false
3224-
3225-
-- 2: Update entities in memory
3226-
for entity, archetypeOld in pairs(self._entitiesUpdated) do
3227-
if (archetypeOld ~= entity.archetype) then
3208+
-- run suspended Tasks
3209+
-- 60FPS = ((1000/60/1000)*0.7)/3 = 0.0038888888888888883
3210+
-- 30FPS = ((1000/30/1000)*0.7)/3 = 0.007777777777777777
3211+
local maxScheduleExecTime = (self._timer.Time.DeltaFixed * (self.maxScheduleExecTimePercent or 0.7))/3
3212+
self._executor:ExecTasks(maxScheduleExecTime)
3213+
end,
3214+
function(Time)
3215+
if step == "process" then
3216+
self._executor:ExecProcess(Time)
3217+
elseif step == "transform" then
3218+
self._executor:ExecTransform(Time)
3219+
else
3220+
self._executor:ExecRender(Time)
3221+
end
3222+
3223+
-- cleans up after running scripts
3224+
while self._dirty do
3225+
self._dirty = false
3226+
3227+
-- 1: remove entities
3228+
local entitiesRemoved = {}
3229+
for entity,_ in pairs(self._entitiesRemoved) do
3230+
entitiesRemoved[entity] = self._entitiesUpdated[entity]
3231+
self._entitiesUpdated[entity] = nil
3232+
end
3233+
self._entitiesRemoved = {}
3234+
self._executor:ExecOnRemove(Time, entitiesRemoved)
3235+
entitiesRemoved = nil
3236+
3237+
local changed = {}
3238+
local hasChange = false
3239+
3240+
-- 2: Update entities in memory
3241+
for entity, archetypeOld in pairs(self._entitiesUpdated) do
3242+
if (archetypeOld ~= entity.archetype) then
3243+
hasChange = true
3244+
changed[entity] = archetypeOld
3245+
end
3246+
end
3247+
self._entitiesUpdated = {}
3248+
3249+
-- 3: Add new entities
3250+
for entity, _ in pairs(self._entitiesCreated) do
32283251
hasChange = true
3229-
changed[entity] = archetypeOld
3252+
changed[entity] = Archetype.EMPTY
3253+
3254+
entity.isAlive = true
3255+
self._repository:Insert(entity)
3256+
end
3257+
self._entitiesCreated = {}
3258+
3259+
if hasChange then
3260+
self._executor:ExecOnExitEnter(Time, changed)
3261+
changed = nil
32303262
end
3231-
end
3232-
self._entitiesUpdated = {}
3233-
3234-
-- 3: Add new entities
3235-
for entity, _ in pairs(self._entitiesCreated) do
3236-
hasChange = true
3237-
changed[entity] = Archetype.EMPTY
3238-
3239-
entity.isAlive = true
3240-
self._repository:Insert(entity)
3241-
end
3242-
self._entitiesCreated = {}
3243-
3244-
if hasChange then
3245-
self._executor:ExecOnExitEnter(Time, changed)
3246-
changed = nil
32473263
end
32483264
end
3249-
end)
3265+
)
32503266
end
32513267

32523268
--[[

README.md

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,63 @@
1717
<strong><a href="https://nidorx.github.io/ecs-lua#/">Read the Documentation</a></strong>
1818
</p>
1919

20-
<p align="center">
21-
<strong>ECS Lua</strong> is a fast and easy to use ECS (Entity Component System) engine for game development.
22-
</p>
20+
# What is it?
21+
22+
<strong>ECS Lua</strong> is a fast and easy to use ECS (Entity Component System) engine for game development.
23+
24+
<div align="center">
25+
26+
![](docs/assets/diagram-1.png)
27+
28+
</div>
29+
30+
The basic idea of this pattern is to stop defining entities using a
31+
[hierarchy](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) of classes and start doing use of
32+
[composition](https://en.wikipedia.org/wiki/Object_composition) in a Data Oriented Programming paradigm.
33+
([More information on Wikipedia](https://en.wikipedia.org/wiki/Entity_component_system)).
34+
Programming with an ECS can result in code that is more efficient and easier to extend over time.
35+
36+
37+
# How does it work?
38+
39+
<div align="center">
40+
41+
![ECS Lua pipeline](docs/assets/pipeline.png)
42+
43+
</div>
44+
45+
46+
# Talk is cheap. Show me the code!
47+
48+
```lua
49+
local World, System, Query, Component = ECS.World, ECS.System, ECS.Query, ECS.Component
50+
51+
local Health = Component(100)
52+
local Position = Component({ x = 0, y = 0})
53+
54+
local isInAcid = Query.Filter(function()
55+
return true -- it's wet season
56+
end)
57+
58+
local InAcidSystem = System("process", Query.All( Health, Position, isInAcid() ))
59+
60+
function InAcidSystem:Update()
61+
for i, entity in self:Result():Iterator() do
62+
local health = entity[Health]
63+
health.value = health.value - 0.01
64+
end
65+
end
66+
67+
local world = World({ InAcidSystem })
68+
69+
world.Entity(Position({ x: 5.0 }), Health())
70+
```
71+
72+
# Features
2373

2474
**ECS Lua** has no external dependencies and is compatible and tested with [Lua 5.1], [Lua 5.2], [Lua 5.3], [Lua 5.4],
2575
[LuaJit] and [Roblox Luau](https://luau-lang.org/)
2676

27-
### Features
28-
2977
- **Game engine agnostic**: It can be used in any engine that has the Lua scripting language.
3078
- **Ergonomic**: Focused on providing a simple yet efficient API
3179
- **FSM**: Finite State Machines in an easy and intuitive way
@@ -35,11 +83,16 @@
3583
- The systems will work in the order they were registered or based on the priority set when registering them.
3684
- Reactive events do not generate a random callback when issued, they are executed at a predefined step.
3785

38-
## Usage
86+
# Goal
87+
88+
To be a lightweight, simple, ergonomic and high-performance ECS library that can be easily extended. The **ECS Lua**
89+
does not strictly follow _"pure ECS design"_.
90+
91+
# Usage
3992

4093
Read our [Full Documentation][docs] to learn how to use **ECS Lua**.
4194

42-
## Get involved
95+
# Get involved
4396
All kinds of contributions are welcome!
4497

4598
🐛 **Found a bug?**
@@ -67,7 +120,7 @@ Pull requests even for small changes can be helpful. Each page in the docs can b
67120
[LuaJit]:https://app.travis-ci.com/github/nidorx/ecs-lua
68121
[coroutines]:http://www.lua.org/pil/9.1.html
69122

70-
## License
123+
# License
71124

72125
This code is distributed under the terms and conditions of the [MIT license](LICENSE).
73126

build.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ local SRC_FILES = {
2323
}
2424

2525
local HEADER = [[
26-
ECS Lua v2.1.0 [2021-10-15 11:00]
26+
ECS Lua v2.1.1
2727
2828
ECS Lua is a fast and easy to use ECS (Entity Component System) engine for game development.
2929

docs/README.md

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,67 @@
1-
# Introduction
1+
# What is it?
22

3-
**ECS Lua** is a lua [ECS _(Entity Component System)_](https://en.wikipedia.org/wiki/Entity_component_system) library
4-
used for game developments.
3+
**ECS Lua** is a fast and easy to use ECS (Entity Component System) engine for game development.
4+
5+
![](assets/diagram-1.png)
6+
7+
The basic idea of this pattern is to stop defining entities using a
8+
[hierarchy](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) of classes and start doing use of
9+
[composition](https://en.wikipedia.org/wiki/Object_composition) in a Data Oriented Programming paradigm.
10+
([More information on Wikipedia](https://en.wikipedia.org/wiki/Entity_component_system)).
11+
Programming with an ECS can result in code that is more efficient and easier to extend over time.
12+
13+
14+
# How does it work?
15+
16+
![ECS Lua pipeline](assets/pipeline.png)
17+
18+
19+
# Talk is cheap. Show me the code!
20+
21+
```lua
22+
local World, System, Query, Component = ECS.World, ECS.System, ECS.Query, ECS.Component
23+
24+
local Health = Component(100)
25+
local Position = Component({ x = 0, y = 0})
26+
27+
local isInAcid = Query.Filter(function()
28+
return true -- it's wet season
29+
end)
30+
31+
local InAcidSystem = System("process", Query.All( Health, Position, isInAcid() ))
32+
33+
function InAcidSystem:Update()
34+
for i, entity in self:Result():Iterator() do
35+
local health = entity[Health]
36+
health.value = health.value - 0.01
37+
end
38+
end
39+
40+
local world = World({ InAcidSystem })
41+
42+
world.Entity(Position({ x: 5.0 }), Health())
43+
```
44+
45+
# Features
546

647
**ECS Lua** has no external dependencies and is compatible and tested with [Lua 5.1], [Lua 5.2], [Lua 5.3], [Lua 5.4],
748
[LuaJit] and [Roblox Luau](https://luau-lang.org/)
8-
9-
## Features
10-
11-
- Game engine agnostic. It can be used in any engine that has the Lua scripting language.
12-
- Focused on providing a simple yet efficient API
13-
- Multiple queries per system
14-
- It has a `JobSystem` for running systems in parallel (through [coroutines](http://www.lua.org/pil/9.1.html))
15-
- Reactive: Systems can be informed when an entity changes
16-
- Predictable:
49+
50+
- **Game engine agnostic**: It can be used in any engine that has the Lua scripting language.
51+
- **Ergonomic**: Focused on providing a simple yet efficient API
52+
- **FSM**: Finite State Machines in an easy and intuitive way
53+
- **JobSystem**: To running systems in parallel (through [coroutines])
54+
- **Reactive**: Systems can be informed when an entity changes
55+
- **Predictable**:
1756
- The systems will work in the order they were registered or based on the priority set when registering them.
1857
- Reactive events do not generate a random callback when issued, they are executed at a predefined step.
1958

20-
## Goal
59+
# Goal
2160

2261
To be a lightweight, simple, ergonomic and high-performance ECS library that can be easily extended. The **ECS Lua**
23-
does not strictly follow "pure ECS design".
62+
does not strictly follow _"pure ECS design"_.
2463

25-
## And now?
64+
# Next steps
2665

2766
You can browse or search for specific subjects in the side menu. Here are some relevant links:
2867

@@ -32,11 +71,11 @@ You can browse or search for specific subjects in the side menu. Here are some r
3271
<div class="home-row clearfix" style="text-align:center">
3372
<div class="home-col"><div class="panel home-panel"><div class="panel-body">
3473

35-
[![Getting Started](assets/icon-basic.png ":no-zoom")](/getting-started?id=getting-started)
74+
[![Installation](assets/icon-download.png ":no-zoom")](/getting-started?id=installation)
3675

3776
</div><div class="panel-heading">
3877

39-
[Getting Started](/getting-started?id=getting-started)
78+
[Installation](/getting-started?id=installation)
4079

4180
</div></div></div>
4281

0 commit comments

Comments
 (0)