24 Commits
v1.4.0 ... main

Author SHA1 Message Date
12a720bd9e Merge pull request #31 from BlackMATov/dev
Dev
2025-11-24 13:49:59 +07:00
BlackMATov
5895c6ee8f v1.5.0 2025-11-24 13:45:55 +07:00
BlackMATov
1c02ba5468 little love2d example 2025-11-24 13:35:34 +07:00
BlackMATov
760b477564 update changelog 2025-11-21 06:31:42 +07:00
BlackMATov
fc910881bd cache defaults/duplicates per chunk, use it for spawn/clone ops 2025-11-21 05:37:14 +07:00
BlackMATov
71a7c84a67 add spawn/clone with defaults bmarks 2025-11-20 16:19:13 +07:00
BlackMATov
582a09a6db additional spawn/clone tests 2025-11-20 05:00:52 +07:00
BlackMATov
de73881f63 improve performance of the clone operations 2025-11-19 08:51:26 +07:00
BlackMATov
55e444ca63 improve performance of the spawn operations 2025-11-19 02:23:48 +07:00
BlackMATov
e499c701ef add defer clone bmarks 2025-11-12 23:44:34 +07:00
BlackMATov
789f167bf4 add defer spawn bmarks 2025-11-12 16:47:38 +07:00
BlackMATov
00367ce07e Merge branch 'feature/teal' into dev 2025-11-08 01:34:29 +07:00
BlackMATov
07902eb184 teal definitions cleanup 2025-11-07 23:26:45 +07:00
ecdbfe660f Merge pull request #30 from p0sel0k/main 2025-11-07 16:03:22 +07:00
p0sel0k
cfd68767cf fix: set and batch_set component argument should be optional 2025-11-04 21:57:00 +03:00
p0sel0k
f1ba9ab909 fix: replace number type with integer; EachState\ExecuteState records 2025-11-04 18:56:02 +03:00
BlackMATov
77ff3e77db readme: internal fragments
https://github.com/BlackMATov/evolved.lua/issues/28
2025-11-04 21:00:22 +07:00
p0sel0k
825eba5328 fix: remove teal types for internal usage 2025-11-04 10:06:01 +03:00
p0sel0k
67002503ed fix: removed IComponent and added generics for functions and hooks that take Component as a single argument 2025-11-03 11:57:18 +03:00
p0sel0k
1bb0089e9f fix: functions arguments naming 2025-11-02 21:21:25 +03:00
p0sel0k
dc642f5294 fix: fixes after review 2025-11-02 21:12:26 +03:00
p0sel0k
a81a8646e9 fix: wrong file name 2025-10-29 19:29:56 +03:00
p0sel0k
aa6d2c1c48 feat: add Teal language definitions 2025-10-29 19:24:07 +03:00
BlackMATov
5fe48de890 little speed up of exclude-only queries 2025-10-29 22:57:58 +07:00
15 changed files with 2329 additions and 721 deletions

View File

@@ -28,6 +28,9 @@
"ignoreDir": [ "ignoreDir": [
".vscode", ".vscode",
"develop/3rdparty" "develop/3rdparty"
],
"library": [
"${3rd}/love2d/library"
] ]
} }
} }

11
.vscode/launch.json vendored
View File

@@ -27,6 +27,17 @@
"lua": "luajit", "lua": "luajit",
"file": "${workspaceFolder}/develop/all.lua" "file": "${workspaceFolder}/develop/all.lua"
} }
},
{
"name": "Launch Evolved Example (LÖVE)",
"type": "lua-local",
"request": "launch",
"program": {
"command": "love"
},
"args": [
"${workspaceFolder}/example"
]
} }
] ]
} }

View File

@@ -1,5 +1,5 @@
{ {
"[json][jsonc][lua][markdown][yaml]": { "[json][jsonc][lua][markdown][teal][yaml]": {
"editor.formatOnSave": true, "editor.formatOnSave": true,
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,

View File

@@ -48,6 +48,7 @@
- [Fragment Hooks](#fragment-hooks) - [Fragment Hooks](#fragment-hooks)
- [Unique Fragments](#unique-fragments) - [Unique Fragments](#unique-fragments)
- [Explicit Fragments](#explicit-fragments) - [Explicit Fragments](#explicit-fragments)
- [Internal Fragments](#internal-fragments)
- [Shared Components](#shared-components) - [Shared Components](#shared-components)
- [Fragment Requirements](#fragment-requirements) - [Fragment Requirements](#fragment-requirements)
- [Destruction Policies](#destruction-policies) - [Destruction Policies](#destruction-policies)
@@ -59,6 +60,7 @@
- [Chunk](#chunk) - [Chunk](#chunk)
- [Builder](#builder) - [Builder](#builder)
- [Changelog](#changelog) - [Changelog](#changelog)
- [v1.5.0](#v150)
- [v1.4.0](#v140) - [v1.4.0](#v140)
- [v1.3.0](#v130) - [v1.3.0](#v130)
- [v1.2.0](#v120) - [v1.2.0](#v120)
@@ -102,7 +104,7 @@ luarocks install evolved.lua
## Quick Start ## Quick Start
To get started with `evolved.lua`, read the [Overview](#overview) section to understand the basic concepts and how to use the library. After that, check the [Samples](develop/samples), which demonstrate complex usage of the library. Finally, refer to the [Cheat Sheet](#cheat-sheet) for a quick reference of all the functions and classes provided by the library. To get started with `evolved.lua`, read the [Overview](#overview) section to understand the basic concepts and how to use the library. After that, check the [Example](example), which demonstrate complex usage of the library. Finally, refer to the [Cheat Sheet](#cheat-sheet) for a quick reference of all the functions and classes provided by the library.
## Overview ## Overview
@@ -964,6 +966,10 @@ local all_enemies_including_disabled = evolved.builder()
:build() :build()
``` ```
#### Internal Fragments
All predefined fragments provided by the library are marked as internal with the [`evolved.INTERNAL`](#evolvedinternal) trait. Because [`evolved.INTERNAL`](#evolvedinternal) is itself marked as [`evolved.EXPLICIT`](#evolvedexplicit), these fragments are hidden from queries by default. This prevents accidental use of internal fragments in user code and helps distinguish them from user-defined fragments.
#### Shared Components #### Shared Components
Often, we want to store components as tables, and by default, these tables will be shared between entities. This means that if you modify the table in one entity, it will be modified in all entities that share this table. Sometimes this is what we want. For example, when we want to share a configuration or some resource between entities. But in other cases, we want each entity to have its own copy of the table. For example, if we want to store the position of an entity as a table, we don't want to share this table with other entities. Yes, we can copy the table manually, but the library provides a little bit of syntactic sugar for this. Often, we want to store components as tables, and by default, these tables will be shared between entities. This means that if you modify the table in one entity, it will be modified in all entities that share this table. Sometimes this is what we want. For example, when we want to share a configuration or some resource between entities. But in other cases, we want each entity to have its own copy of the table. For example, if we want to store the position of an entity as a table, we don't want to share this table with other entities. Yes, we can copy the table manually, but the library provides a little bit of syntactic sugar for this.
@@ -1300,6 +1306,12 @@ builder_mt:destruction_policy :: id -> builder
## Changelog ## Changelog
### v1.5.0
- Added a little [LÖVE](https://love2d.org) example;
- The spawn and clone operations with defaults have been significantly optimized;
- Added basic [Teal](https://github.com/teal-language) type definitions, thanks to [@p0sel0k](https://github.com/p0sel0k).
### v1.4.0 ### v1.4.0
- Improved query execution performance by caching some internal calculations - Improved query execution performance by caching some internal calculations
@@ -1939,7 +1951,7 @@ function evolved.builder_mt:internal() end
#### `evolved.builder_mt:default` #### `evolved.builder_mt:default`
```lua ```lua
---@param default evolved.component ---@param default evolved.default
---@return evolved.builder builder ---@return evolved.builder builder
function evolved.builder_mt:default(default) end function evolved.builder_mt:default(default) end
``` ```

View File

@@ -1,12 +1,12 @@
require 'develop.samples.systems'
require 'develop.testing.build_tests' require 'develop.testing.build_tests'
require 'develop.testing.cancel_tests' require 'develop.testing.cancel_tests'
require 'develop.testing.clone_tests'
require 'develop.testing.locate_tests' require 'develop.testing.locate_tests'
require 'develop.testing.main_tests' require 'develop.testing.main_tests'
require 'develop.testing.multi_spawn_tests' require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests' require 'develop.testing.name_tests'
require 'develop.testing.requires_fragment_tests' require 'develop.testing.requires_fragment_tests'
require 'develop.testing.spawn_tests'
require 'develop.testing.system_as_query_tests' require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.clone_bmarks' require 'develop.benchmarks.clone_bmarks'

View File

@@ -6,16 +6,35 @@ evo.debug_mode(false)
local N = 1000 local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5) local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn() evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
local R1 = evo.builder():require(F1):spawn() evo.set(D1, evo.DUPLICATE, function(v) return not v end)
local R3 = evo.builder():require(F1, F2, F3):spawn() evo.set(D2, evo.DUPLICATE, function(v) return not v end)
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn() evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function() function()
local clone = evo.clone local clone = evo.clone
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab) clone(prefab)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
function() function()
local clone = evo.clone local clone = evo.clone
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab) clone(prefab)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function() function()
local clone = evo.clone local clone = evo.clone
@@ -51,53 +132,177 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab) clone(prefab)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N),
function() function()
local clone = evo.clone local clone = evo.clone
local prefab = evo.spawn { [R1] = true } local prefab = evo.spawn { [RF1] = true }
for _ = 1, N do for _ = 1, N do
clone(prefab) clone(prefab)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 required component', N),
function() function()
local clone = evo.clone local clone = evo.clone
local prefab = evo.spawn { [R3] = true } local prefab = evo.spawn { [RF1] = true }
evo.defer()
for _ = 1, N do for _ = 1, N do
clone(prefab) clone(prefab)
end end
evo.commit()
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N), basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 required component', N),
function() function()
local clone = evo.clone local clone = evo.clone
local prefab = evo.spawn { [R5] = true } local prefab = evo.spawn { [RD1] = true }
for _ = 1, N do for _ = 1, N do
clone(prefab) clone(prefab)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD123] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD12345] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
@@ -105,10 +310,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab) multi_clone(N, prefab)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
@@ -116,10 +348,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab) multi_clone(N, prefab)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
@@ -127,40 +386,147 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab) multi_clone(N, prefab)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R1] = true } local prefab = evo.spawn { [RF1] = true }
multi_clone(N, prefab) multi_clone(N, prefab)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 required component', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R3] = true } local prefab = evo.spawn { [RF1] = true }
evo.defer()
multi_clone(N, prefab) multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N), basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 required component', N),
function() function()
local multi_clone = evo.multi_clone local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R5] = true } local prefab = evo.spawn { [RD1] = true }
multi_clone(N, prefab) multi_clone(N, prefab)
evo.batch_destroy(Q1) evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD123] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
multi_clone(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 required components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [RD12345] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end) end)

View File

@@ -6,16 +6,35 @@ evo.debug_mode(false)
local N = 1000 local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5) local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn() evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
local R1 = evo.builder():require(F1):spawn() evo.set(D1, evo.DUPLICATE, function(v) return not v end)
local R3 = evo.builder():require(F1, F2, F3):spawn() evo.set(D2, evo.DUPLICATE, function(v) return not v end)
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn() evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components) spawn(components)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [D1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components) spawn(components)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
@@ -51,53 +132,177 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components) spawn(components)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
local components = { [R1] = true } local components = { [RF1] = true }
for _ = 1, N do for _ = 1, N do
spawn(components) spawn(components)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 required component', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
local components = { [R3] = true } local components = { [RF1] = true }
evo.defer()
for _ = 1, N do for _ = 1, N do
spawn(components) spawn(components)
end end
evo.commit()
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 required component', N),
function() function()
local spawn = evo.spawn local spawn = evo.spawn
local components = { [R5] = true } local components = { [RD1] = true }
for _ = 1, N do for _ = 1, N do
spawn(components) spawn(components)
end end
evo.batch_destroy(Q1) evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RD123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RD12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
function() function()
local builder = evo.builder():set(F1) local builder = evo.builder():set(F1)
@@ -105,10 +310,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn() builder:spawn()
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 component', N),
function()
local builder = evo.builder():set(D1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
function() function()
local builder = evo.builder():set(F1):set(F2):set(F3) local builder = evo.builder():set(F1):set(F2):set(F3)
@@ -116,10 +348,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn() builder:spawn()
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
function() function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5) local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
@@ -127,47 +386,155 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn() builder:spawn()
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3):set(D4):set(D5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
function() function()
local builder = evo.builder():set(R1) local builder = evo.builder():set(RF1)
for _ = 1, N do for _ = 1, N do
builder:spawn() builder:spawn()
end end
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 required component', N),
function() function()
local builder = evo.builder():set(R3) local builder = evo.builder():set(RF1)
evo.defer()
for _ = 1, N do for _ = 1, N do
builder:spawn() builder:spawn()
end end
evo.commit()
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 required component', N),
function() function()
local builder = evo.builder():set(R5) local builder = evo.builder():set(RD1)
for _ = 1, N do for _ = 1, N do
builder:spawn() builder:spawn()
end end
evo.batch_destroy(Q1) evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RD123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RD12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
@@ -175,10 +542,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components) multi_spawn(N, components)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
@@ -186,10 +580,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components) multi_spawn(N, components)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
@@ -197,12 +618,39 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components) multi_spawn(N, components)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end) end)
print '----------------------------------------' print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
@@ -210,27 +658,107 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components) multi_spawn(N, components)
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 required component', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
local components = { [R3] = true } local components = { [F1] = true }
evo.defer()
multi_spawn(N, components) multi_spawn(N, components)
evo.commit()
evo.batch_destroy(Q1) evo.batch_destroy(QF1)
end) end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N), basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 required component', N),
function() function()
local multi_spawn = evo.multi_spawn local multi_spawn = evo.multi_spawn
local components = { [R5] = true } local components = { [D1] = true }
multi_spawn(N, components) multi_spawn(N, components)
evo.batch_destroy(Q1) evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF123] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RD123] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
multi_spawn(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RF12345] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 required components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [RD12345] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end) end)

View File

@@ -1,129 +0,0 @@
---@diagnostic disable: unused-local
local evo = require 'evolved'
evo.debug_mode(true)
---@class evolved.vector2
---@field x number
---@field y number
---@param x number
---@param y number
---@return evolved.vector2
---@nodiscard
local function vector2(x, y)
---@type evolved.vector2
return { x = x, y = y }
end
local consts = {
delta_time = 0.016,
physics_gravity = vector2(0, 9.81),
}
local groups = {
awake = evo.spawn(),
physics = evo.spawn(),
graphics = evo.spawn(),
shutdown = evo.spawn(),
}
local fragments = {
force = evo.spawn(),
position = evo.spawn(),
velocity = evo.spawn(),
}
local queries = {
physics_bodies = evo.builder()
:include(fragments.force, fragments.position, fragments.velocity)
:spawn(),
}
local awake_system = evo.builder()
:group(groups.awake)
:prologue(function()
print '-= | Awake | =-'
evo.builder()
:set(fragments.force, vector2(0, 0))
:set(fragments.position, vector2(0, 0))
:set(fragments.velocity, vector2(0, 0))
:spawn()
end):spawn()
local integrate_forces_system = evo.builder()
:group(groups.physics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
local delta_time, physics_gravity =
consts.delta_time, consts.physics_gravity
---@type evolved.vector2[], evolved.vector2[]
local forces, velocities = chunk:components(
fragments.force, fragments.velocity)
for i = 1, entity_count do
local force, velocity = forces[i], velocities[i]
velocity.x = velocity.x + (physics_gravity.x + force.x) * delta_time
velocity.y = velocity.y + (physics_gravity.y + force.y) * delta_time
end
end):spawn()
local integrate_velocities_system = evo.builder()
:group(groups.physics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
local delta_time =
consts.delta_time
---@type evolved.vector2[], evolved.vector2[], evolved.vector2[]
local forces, positions, velocities = chunk:components(
fragments.force, fragments.position, fragments.velocity)
for i = 1, entity_count do
local force, position, velocity = forces[i], positions[i], velocities[i]
position.x = position.x + velocity.x * delta_time
position.y = position.y + velocity.y * delta_time
force.x = 0
force.y = 0
end
end):spawn()
local graphics_system = evo.builder()
:group(groups.graphics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
---@type evolved.vector2[]
local positions = chunk:components(
fragments.position)
for i = 1, entity_count do
local entity, position = entities[i], positions[i]
print(string.format(
'|-> {entity %d} at {%.4f, %.4f}',
entity, position.x, position.y))
end
end):spawn()
local shutdown_system = evo.builder()
:group(groups.shutdown)
:epilogue(function()
print '-= | Shutdown | =-'
evo.batch_destroy(queries.physics_bodies)
end):spawn()
do
evo.process(groups.awake)
for _ = 1, 10 do
evo.process(groups.physics)
evo.process(groups.graphics)
end
evo.process(groups.shutdown)
end

View File

@@ -0,0 +1,397 @@
local evo = require 'evolved'
do
do
local p = evo.spawn()
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn()
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f2, evo.DEFAULT, 42)
local p = evo.spawn()
local e = evo.clone(p, { [f1] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2))
assert(evo.has(e, f1) and evo.get(e, f1) == 'hello')
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f3] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f3) and evo.get(e, f3) == 10)
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == 'hello')
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 200 * 2)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p)
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, { [f4] = 'another' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f3] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 10)
end
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 'hello')
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p)
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, {})
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, { [f4] = 'another' })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 200 * 2)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f2] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p, { [f1] = 'hello', [f2] = 10 })
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
end

View File

@@ -0,0 +1,329 @@
local evo = require 'evolved'
do
do
local e = evo.spawn()
assert(evo.alive(e) and evo.empty(e))
end
do
local e = evo.spawn({})
assert(evo.alive(e) and evo.empty(e))
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == 21)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.REQUIRES, { f1, f3, f4 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.DUPLICATE, function(v) return v * 3 end)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = true })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == 21 * 3)
assert(evo.has(e, f4) and evo.get(e, f4) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
f3_set_count, f3_inserted_count = 0, 0
local e = evo.spawn({ [f1] = 'hello', [f2] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 and f2_inserted_sum == 42)
assert(f3_set_count == 1 and f3_inserted_count == 1)
end
end
do
do
local es, ec = evo.multi_spawn(2)
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local es, ec = evo.multi_spawn(2, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
end
do
local f1, f2 = evo.id(2)
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
local es, ec = evo.multi_spawn(3, { [f1] = 42, [f2] = 'hello' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(1, { [f1] = 42 })
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 'hello')
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world', [f3] = false })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == false)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f1, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.DEFAULT, 'hello')
evo.set(f2, evo.DUPLICATE, function(v) return v .. '!' end)
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f2] = 'hello world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello world!')
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
local es, ec = evo.multi_spawn(3, { [f1] = 'hello', [f2] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 * 3 and f2_inserted_sum == 42 * 3)
assert(f3_set_count == 3 and f3_inserted_count == 3)
end
end
end

181
evolved.d.tl Normal file
View File

@@ -0,0 +1,181 @@
local record Evolved
interface Id end
type Entity = Id
type Fragment = Id
type Query = Id
type System = Id
interface EachState end
interface ExecuteState end
type EachIterator = function(state?: EachState): Fragment, any
type ExecuteIterator = function(state?: ExecuteState): Chunk, { Entity }, integer
interface Chunk
alive: function(self: Chunk): boolean
empty: function(self: Chunk): boolean
has: function(self: Chunk, fragment: Fragment): boolean
has_all: function(self: Chunk, ...: Fragment): boolean
has_any: function(self: Chunk, ...: Fragment): boolean
entities: function(self: Chunk): { Entity }, integer
fragments: function(self: Chunk): { Fragment }, integer
components: function(self: Chunk)
components: function<C1>(self: Chunk, f1: Fragment): { C1 }
components: function<C1, C2>(self: Chunk, f1: Fragment, f2: Fragment): { C1 }, { C2 }
components: function<C1, C2, C3>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment): { C1 }, { C2 }, { C3 }
components: function<C1, C2, C3, C4>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): { C1 }, { C2 }, { C3 }, { C4 }
end
interface Builder
build: function(self: Builder, prefab?: Entity): Entity
multi_build: function(self: Builder, entity_count: integer, prefab?: Entity): { Entity }, integer
spawn: function(self: Builder): Entity
multi_spawn: function(self: Builder, entity_count: integer): { Entity }, integer
clone: function(self: Builder, prefab: Entity): Entity
multi_clone: function(self: Builder, entity_count: integer, prefab: Entity): { Entity }, integer
has: function(self: Builder, fragment: Fragment): boolean
has_all: function(self: Builder, ...: Fragment): boolean
has_any: function(self: Builder, ...: Fragment): boolean
get: function(self: Builder)
get: function<C1>(self: Builder, f1: Fragment): C1 | nil
get: function<C1, C2>(self: Builder, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(self: Builder, fragment: Fragment, component?: Component): Builder
remove: function(self: Builder, ...: Fragment): Builder
clear: function(self: Builder): Builder
tag: function(self: Builder): Builder
name: function(self: Builder, name: string): Builder
unique: function(self: Builder): Builder
explicit: function(self: Builder): Builder
internal: function(self: Builder): Builder
default: function<Component>(self: Builder, default: Component): Builder
duplicate: function<Component>(self: Builder, duplicate: function(Component): Component): Builder
prefab: function(self: Builder): Builder
disabled: function(self: Builder): Builder
include: function(self: Builder, ...: Fragment): Builder
exclude: function(self: Builder, ...: Fragment): Builder
require: function(self: Builder, ...: Fragment): Builder
on_set: function<Component>(self: Builder, on_set: function(Entity, Fragment, ? Component, ? Component)): Builder
on_assign: function<Component>(self: Builder, on_assign: function(Entity, Fragment, ? Component, ? Component)): Builder
on_insert: function<Component>(self: Builder, on_insert: function(Entity, Fragment, ? Component)): Builder
on_remove: function<Component>(self: Builder, on_remove: function(Entity, Fragment, ? Component)): Builder
group: function(self: Builder, group: System): Builder
query: function(self: Builder, query: Query): Builder
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer)): Builder
prologue: function(self: Builder, prologue: function()): Builder
epilogue: function(self: Builder, epilogue: function()): Builder
destruction_policy: function(self: Builder, destruction_policy: Id): Builder
end
TAG: Fragment
NAME: Fragment
UNIQUE: Fragment
EXPLICIT: Fragment
INTERNAL: Fragment
DEFAULT: Fragment
DUPLICATE: Fragment
PREFAB: Fragment
DISABLED: Fragment
INCLUDES: Fragment
EXCLUDES: Fragment
REQUIRES: Fragment
ON_SET: Fragment
ON_ASSIGN: Fragment
ON_INSERT: Fragment
ON_REMOVE: Fragment
GROUP: Fragment
QUERY: Fragment
EXECUTE: Fragment
PROLOGUE: Fragment
EPILOGUE: Fragment
DESTRUCTION_POLICY: Fragment
DESTRUCTION_POLICY_DESTROY_ENTITY: Id
DESTRUCTION_POLICY_REMOVE_FRAGMENT: Id
id: function(count?: integer): Id...
name: function(...: Id): string...
pack: function(primary: integer, secondary: integer): Id
unpack: function(id: Id): integer, integer
defer: function(): boolean
commit: function(): boolean
cancel: function(): boolean
spawn: function(components?: { Fragment: any }): Entity
multi_spawn: function(entity_count: integer, components?: { Fragment: any }): { Entity }, integer
clone: function(prefab: Entity, components?: { Fragment: any }): Entity
multi_clone: function(entity_count: integer, prefab: Entity, components?: { Fragment: any }): { Entity }, integer
alive: function(entity: Entity): boolean
alive_all: function(...: Entity): boolean
alive_any: function(...: Entity): boolean
empty: function(entity: Entity): boolean
empty_all: function(...: Entity): boolean
empty_any: function(...: Entity): boolean
has: function(entity: Entity, fragment: Fragment): boolean
has_all: function(entity: Entity, ...: Fragment): boolean
has_any: function(entity: Entity, ...: Fragment): boolean
get: function(entity: Entity)
get: function<C1>(entity: Entity, f1: Fragment): C1 | nil
get: function<C1, C2>(entity: Entity, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(entity: Entity, fragment: Fragment, component?: Component)
remove: function(entity: Entity, ...: Fragment)
clear: function(...: Entity)
destroy: function(...: Entity)
batch_set: function<Component>(query: Query, fragment: Fragment, component?: Component)
batch_remove: function(query: Query, ...: Fragment)
batch_clear: function(...: Query)
batch_destroy: function(...: Query)
each: function(entity: Entity): EachIterator, EachState | nil
execute: function(query: Query): ExecuteIterator, ExecuteState | nil
locate: function(entity: Entity): Chunk | nil, integer
process: function(...: System)
debug_mode: function(yesno: boolean)
collect_garbage: function()
chunk: function(fragment: Fragment, ...: Fragment): Chunk, { Entity }, integer
builder: function(): Builder
end
return Evolved

View File

@@ -1,7 +1,7 @@
local evolved = { local evolved = {
__HOMEPAGE = 'https://github.com/BlackMATov/evolved.lua', __HOMEPAGE = 'https://github.com/BlackMATov/evolved.lua',
__DESCRIPTION = 'Evolved ECS (Entity-Component-System) for Lua', __DESCRIPTION = 'Evolved ECS (Entity-Component-System) for Lua',
__VERSION = '1.4.0', __VERSION = '1.5.0',
__LICENSE = [[ __LICENSE = [[
MIT License MIT License
@@ -52,7 +52,7 @@ local evolved = {
--- entity: evolved.entity, --- entity: evolved.entity,
--- fragment: evolved.fragment, --- fragment: evolved.fragment,
--- new_component: evolved.component, --- new_component: evolved.component,
--- old_component?: evolved.component) --- old_component: evolved.component)
---@alias evolved.assign_hook fun( ---@alias evolved.assign_hook fun(
--- entity: evolved.entity, --- entity: evolved.entity,
@@ -68,7 +68,7 @@ local evolved = {
---@alias evolved.remove_hook fun( ---@alias evolved.remove_hook fun(
--- entity: evolved.entity, --- entity: evolved.entity,
--- fragment: evolved.fragment, --- fragment: evolved.fragment,
--- component: evolved.component) --- old_component: evolved.component)
---@class (exact) evolved.each_state ---@class (exact) evolved.each_state
---@field package [1] integer structural_changes ---@field package [1] integer structural_changes
@@ -162,6 +162,8 @@ local __group_subsystems = {} ---@type table<evolved.system, evolved.assoc_list<
---@field package __component_indices table<evolved.fragment, integer> ---@field package __component_indices table<evolved.fragment, integer>
---@field package __component_storages evolved.storage[] ---@field package __component_storages evolved.storage[]
---@field package __component_fragments evolved.fragment[] ---@field package __component_fragments evolved.fragment[]
---@field package __component_defaults evolved.default[]
---@field package __component_duplicates evolved.duplicate[]
---@field package __with_fragment_edges table<evolved.fragment, evolved.chunk> ---@field package __with_fragment_edges table<evolved.fragment, evolved.chunk>
---@field package __without_fragment_edges table<evolved.fragment, evolved.chunk> ---@field package __without_fragment_edges table<evolved.fragment, evolved.chunk>
---@field package __without_unique_fragments? evolved.chunk ---@field package __without_unique_fragments? evolved.chunk
@@ -997,6 +999,8 @@ function __new_chunk(chunk_parent, chunk_fragment)
__component_indices = {}, __component_indices = {},
__component_storages = {}, __component_storages = {},
__component_fragments = {}, __component_fragments = {},
__component_defaults = {},
__component_duplicates = {},
__with_fragment_edges = {}, __with_fragment_edges = {},
__without_fragment_edges = {}, __without_fragment_edges = {},
__without_unique_fragments = nil, __without_unique_fragments = nil,
@@ -1158,26 +1162,38 @@ function __update_chunk_storages(chunk)
local component_indices = chunk.__component_indices local component_indices = chunk.__component_indices
local component_storages = chunk.__component_storages local component_storages = chunk.__component_storages
local component_fragments = chunk.__component_fragments local component_fragments = chunk.__component_fragments
local component_defaults = chunk.__component_defaults
local component_duplicates = chunk.__component_duplicates
for fragment_index = 1, fragment_count do for fragment_index = 1, fragment_count do
local fragment = fragment_list[fragment_index] local fragment = fragment_list[fragment_index]
local component_index = component_indices[fragment] local component_index = component_indices[fragment]
---@type evolved.default?, evolved.duplicate?
local fragment_default, fragment_duplicate =
__evolved_get(fragment, __DEFAULT, __DUPLICATE)
local is_fragment_tag = __evolved_has(fragment, __TAG) local is_fragment_tag = __evolved_has(fragment, __TAG)
if component_index and is_fragment_tag then if component_index and is_fragment_tag then
if component_index ~= component_count then if component_index ~= component_count then
local last_component_storage = component_storages[component_count] local last_component_storage = component_storages[component_count]
local last_component_fragment = component_fragments[component_count] local last_component_fragment = component_fragments[component_count]
local last_component_default = component_defaults[component_count]
local last_component_duplicate = component_duplicates[component_count]
component_indices[last_component_fragment] = component_index component_indices[last_component_fragment] = component_index
component_storages[component_index] = last_component_storage component_storages[component_index] = last_component_storage
component_fragments[component_index] = last_component_fragment component_fragments[component_index] = last_component_fragment
component_defaults[component_index] = last_component_default
component_duplicates[component_index] = last_component_duplicate
end end
component_indices[fragment] = nil component_indices[fragment] = nil
component_storages[component_count] = nil component_storages[component_count] = nil
component_fragments[component_count] = nil component_fragments[component_count] = nil
component_defaults[component_count] = nil
component_duplicates[component_count] = nil
component_count = component_count - 1 component_count = component_count - 1
chunk.__component_count = component_count chunk.__component_count = component_count
@@ -1191,10 +1207,8 @@ function __update_chunk_storages(chunk)
component_indices[fragment] = component_storage_index component_indices[fragment] = component_storage_index
component_storages[component_storage_index] = component_storage component_storages[component_storage_index] = component_storage
component_fragments[component_storage_index] = fragment component_fragments[component_storage_index] = fragment
component_defaults[component_storage_index] = fragment_default
---@type evolved.default?, evolved.duplicate? component_duplicates[component_storage_index] = fragment_duplicate
local fragment_default, fragment_duplicate =
__evolved_get(fragment, __DEFAULT, __DUPLICATE)
if fragment_duplicate then if fragment_duplicate then
for place = 1, entity_count do for place = 1, entity_count do
@@ -1210,6 +1224,9 @@ function __update_chunk_storages(chunk)
component_storage[place] = new_component component_storage[place] = new_component
end end
end end
elseif component_index then
component_defaults[component_index] = fragment_default
component_duplicates[component_index] = fragment_duplicate
end end
end end
end end
@@ -2009,9 +2026,6 @@ function __spawn_entity(chunk, entity, components)
local req_fragment_list local req_fragment_list
local req_fragment_count = 0 local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer> ---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set) req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2019,7 +2033,7 @@ function __spawn_entity(chunk, entity, components)
---@type evolved.fragment[] ---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list) req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk, req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count) req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do for req_fragment_index = 1, req_fragment_count do
@@ -2031,8 +2045,12 @@ function __spawn_entity(chunk, entity, components)
local chunk_entity_list = chunk.__entity_list local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local chunk_component_defaults = chunk.__component_defaults
local chunk_component_duplicates = chunk.__component_duplicates
local place = chunk_entity_count + 1 local place = chunk_entity_count + 1
@@ -2047,88 +2065,31 @@ function __spawn_entity(chunk, entity, components)
__entity_places[entity_primary] = place __entity_places[entity_primary] = place
end end
if chunk.__has_setup_hooks then for component_index = 1, chunk_component_count do
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
---@type evolved.duplicate? local ini_component = components[component_fragment]
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local new_component = component if ini_component == nil then
ini_component = chunk_component_defaults[component_index]
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
end end
if ini_component ~= nil and component_duplicate then
local new_component = component_duplicate(ini_component)
if new_component == nil then if new_component == nil then
new_component = true new_component = true
end end
component_storage[place] = new_component component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else else
local req_component_index = chunk_component_indices[req_fragment] if ini_component == nil then
ini_component = true
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
local req_component = req_fragment_default
if req_component ~= nil and req_fragment_duplicate then
req_component = req_fragment_duplicate(req_component)
end end
if req_component == nil then component_storage[place] = ini_component
req_component = true
end
req_component_storage[place] = req_component
end
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local new_component = component
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
req_component_storage[place] = req_component
end
end
end end
end end
@@ -2143,6 +2104,7 @@ function __spawn_entity(chunk, entity, components)
local fragment_on_set, fragment_on_insert = local fragment_on_set, fragment_on_insert =
__evolved_get(fragment, __ON_SET, __ON_INSERT) __evolved_get(fragment, __ON_SET, __ON_INSERT)
if fragment_on_set or fragment_on_insert then
local component_index = chunk_component_indices[fragment] local component_index = chunk_component_indices[fragment]
if component_index then if component_index then
@@ -2168,6 +2130,7 @@ function __spawn_entity(chunk, entity, components)
end end
end end
end end
end
if req_fragment_set then if req_fragment_set then
__release_table(__table_pool_tag.fragment_set, req_fragment_set) __release_table(__table_pool_tag.fragment_set, req_fragment_set)
@@ -2199,9 +2162,6 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local req_fragment_list local req_fragment_list
local req_fragment_count = 0 local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer> ---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set) req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2209,7 +2169,7 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
---@type evolved.fragment[] ---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list) req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk, req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count) req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do for req_fragment_index = 1, req_fragment_count do
@@ -2221,8 +2181,12 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local chunk_entity_list = chunk.__entity_list local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local chunk_component_defaults = chunk.__component_defaults
local chunk_component_duplicates = chunk.__component_duplicates
local b_place = chunk_entity_count + 1 local b_place = chunk_entity_count + 1
local e_place = chunk_entity_count + entity_count local e_place = chunk_entity_count + entity_count
@@ -2244,97 +2208,34 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
end end
end end
if chunk.__has_setup_hooks then for component_index = 1, chunk_component_count do
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
---@type evolved.duplicate? local ini_component = components[component_fragment]
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
if fragment_duplicate then if ini_component == nil then
ini_component = chunk_component_defaults[component_index]
end
if ini_component ~= nil and component_duplicate then
for place = b_place, e_place do for place = b_place, e_place do
local new_component = component local new_component = component_duplicate(ini_component)
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end if new_component == nil then
new_component = true
end
component_storage[place] = new_component component_storage[place] = new_component
end end
else else
local new_component = component if ini_component == nil then
if new_component == nil then new_component = true end ini_component = true
end
for place = b_place, e_place do for place = b_place, e_place do
component_storage[place] = new_component component_storage[place] = ini_component
end
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
if req_fragment_duplicate then
for place = b_place, e_place do
local req_component = req_fragment_default
if req_component ~= nil then req_component = req_fragment_duplicate(req_component) end
if req_component == nil then req_component = true end
req_component_storage[place] = req_component
end
else
local req_component = req_fragment_default
if req_component == nil then req_component = true end
for place = b_place, e_place do
req_component_storage[place] = req_component
end
end
end
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local new_component = component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
for place = b_place, e_place do
req_component_storage[place] = req_component
end
end
end end
end end
end end
@@ -2350,12 +2251,12 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
local fragment_on_set, fragment_on_insert = local fragment_on_set, fragment_on_insert =
__evolved_get(fragment, __ON_SET, __ON_INSERT) __evolved_get(fragment, __ON_SET, __ON_INSERT)
if fragment_on_set or fragment_on_insert then
local component_index = chunk_component_indices[fragment] local component_index = chunk_component_indices[fragment]
if component_index then if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
if fragment_on_set or fragment_on_insert then
for place = b_place, e_place do for place = b_place, e_place do
local entity = chunk_entity_list[place] local entity = chunk_entity_list[place]
@@ -2370,10 +2271,6 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
end end
end end
else else
-- nothing
end
else
if fragment_on_set or fragment_on_insert then
for place = b_place, e_place do for place = b_place, e_place do
local entity = chunk_entity_list[place] local entity = chunk_entity_list[place]
@@ -2385,8 +2282,6 @@ function __multi_spawn_entity(chunk, entity_list, entity_count, components)
fragment_on_insert(entity, fragment) fragment_on_insert(entity, fragment)
end end
end end
else
-- nothing
end end
end end
end end
@@ -2415,8 +2310,12 @@ function __clone_entity(prefab, entity, components)
prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk) prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk)
end end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __spawn_entity(nil, entity, components)
end
local chunk = __chunk_with_components( local chunk = __chunk_with_components(
prefab_chunk and prefab_chunk.__without_unique_fragments, prefab_chunk.__without_unique_fragments,
components) components)
if not chunk then if not chunk then
@@ -2427,9 +2326,6 @@ function __clone_entity(prefab, entity, components)
local req_fragment_list local req_fragment_list
local req_fragment_count = 0 local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer> ---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set) req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2437,7 +2333,7 @@ function __clone_entity(prefab, entity, components)
---@type evolved.fragment[] ---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list) req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk, req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count) req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do for req_fragment_index = 1, req_fragment_count do
@@ -2449,8 +2345,15 @@ function __clone_entity(prefab, entity, components)
local chunk_entity_list = chunk.__entity_list local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local chunk_component_defaults = chunk.__component_defaults
local chunk_component_duplicates = chunk.__component_duplicates
local prefab_component_indices = prefab_chunk.__component_indices
local prefab_component_storages = prefab_chunk.__component_storages
local place = chunk_entity_count + 1 local place = chunk_entity_count + 1
@@ -2465,144 +2368,41 @@ function __clone_entity(prefab, entity, components)
__entity_places[entity_primary] = place __entity_places[entity_primary] = place
end end
if prefab_chunk then for component_index = 1, chunk_component_count do
local prefab_component_count = prefab_chunk.__component_count
local prefab_component_storages = prefab_chunk.__component_storages
local prefab_component_fragments = prefab_chunk.__component_fragments
if prefab_chunk.__has_setup_hooks then
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
---@type evolved.duplicate? local ini_component = components[component_fragment]
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index] local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place] ini_component = prefab_component_storage[prefab_place]
else
local new_component = prefab_component ini_component = chunk_component_defaults[component_index]
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
end end
end
end
if ini_component ~= nil and component_duplicate then
local new_component = component_duplicate(ini_component)
if new_component == nil then if new_component == nil then
new_component = true new_component = true
end end
component_storage[place] = new_component component_storage[place] = new_component
end
end
else else
for prefab_component_index = 1, prefab_component_count do if ini_component == nil then
local fragment = prefab_component_fragments[prefab_component_index] ini_component = true
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
local new_component = prefab_component
if new_component == nil then
new_component = true
end end
component_storage[place] = new_component component_storage[place] = ini_component
end
end
end
end
if chunk.__has_setup_hooks then
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
local new_component = component
if new_component ~= nil and fragment_duplicate then
new_component = fragment_duplicate(new_component)
end
if new_component == nil then
new_component = true
end
component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
local req_component = req_fragment_default
if req_component ~= nil and req_fragment_duplicate then
req_component = req_fragment_duplicate(req_component)
end
if req_component == nil then
req_component = true
end
req_component_storage[place] = req_component
end
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local new_component = component
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
req_component_storage[place] = req_component
end
end
end end
end end
@@ -2617,6 +2417,7 @@ function __clone_entity(prefab, entity, components)
local fragment_on_set, fragment_on_insert = local fragment_on_set, fragment_on_insert =
__evolved_get(fragment, __ON_SET, __ON_INSERT) __evolved_get(fragment, __ON_SET, __ON_INSERT)
if fragment_on_set or fragment_on_insert then
local component_index = chunk_component_indices[fragment] local component_index = chunk_component_indices[fragment]
if component_index then if component_index then
@@ -2642,6 +2443,7 @@ function __clone_entity(prefab, entity, components)
end end
end end
end end
end
if req_fragment_set then if req_fragment_set then
__release_table(__table_pool_tag.fragment_set, req_fragment_set) __release_table(__table_pool_tag.fragment_set, req_fragment_set)
@@ -2667,8 +2469,12 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk) prefab_chunk.__without_unique_fragments = __chunk_without_unique_fragments(prefab_chunk)
end end
if not prefab_chunk or not prefab_chunk.__without_unique_fragments then
return __multi_spawn_entity(nil, entity_list, entity_count, components)
end
local chunk = __chunk_with_components( local chunk = __chunk_with_components(
prefab_chunk and prefab_chunk.__without_unique_fragments, prefab_chunk.__without_unique_fragments,
components) components)
if not chunk then if not chunk then
@@ -2679,9 +2485,6 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local req_fragment_list local req_fragment_list
local req_fragment_count = 0 local req_fragment_count = 0
local ini_chunk = chunk
local ini_fragment_set = ini_chunk.__fragment_set
if chunk.__has_required_fragments then if chunk.__has_required_fragments then
---@type table<evolved.fragment, integer> ---@type table<evolved.fragment, integer>
req_fragment_set = __acquire_table(__table_pool_tag.fragment_set) req_fragment_set = __acquire_table(__table_pool_tag.fragment_set)
@@ -2689,7 +2492,7 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
---@type evolved.fragment[] ---@type evolved.fragment[]
req_fragment_list = __acquire_table(__table_pool_tag.fragment_list) req_fragment_list = __acquire_table(__table_pool_tag.fragment_list)
req_fragment_count = __chunk_required_fragments(ini_chunk, req_fragment_count = __chunk_required_fragments(chunk,
req_fragment_set, req_fragment_list, req_fragment_count) req_fragment_set, req_fragment_list, req_fragment_count)
for req_fragment_index = 1, req_fragment_count do for req_fragment_index = 1, req_fragment_count do
@@ -2701,8 +2504,15 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local chunk_entity_list = chunk.__entity_list local chunk_entity_list = chunk.__entity_list
local chunk_entity_count = chunk.__entity_count local chunk_entity_count = chunk.__entity_count
local chunk_component_count = chunk.__component_count
local chunk_component_indices = chunk.__component_indices local chunk_component_indices = chunk.__component_indices
local chunk_component_storages = chunk.__component_storages local chunk_component_storages = chunk.__component_storages
local chunk_component_fragments = chunk.__component_fragments
local chunk_component_defaults = chunk.__component_defaults
local chunk_component_duplicates = chunk.__component_duplicates
local prefab_component_indices = prefab_chunk.__component_indices
local prefab_component_storages = prefab_chunk.__component_storages
local b_place = chunk_entity_count + 1 local b_place = chunk_entity_count + 1
local e_place = chunk_entity_count + entity_count local e_place = chunk_entity_count + entity_count
@@ -2724,154 +2534,44 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
end end
end end
if prefab_chunk then for component_index = 1, chunk_component_count do
local prefab_component_count = prefab_chunk.__component_count
local prefab_component_storages = prefab_chunk.__component_storages
local prefab_component_fragments = prefab_chunk.__component_fragments
if prefab_chunk.__has_setup_hooks then
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
local component_fragment = chunk_component_fragments[component_index]
local component_duplicate = chunk_component_duplicates[component_index]
---@type evolved.duplicate? local ini_component = components[component_fragment]
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
if ini_component == nil then
if chunk == prefab_chunk then
ini_component = component_storage[prefab_place]
else
local prefab_component_index = prefab_component_indices[component_fragment]
if prefab_component_index then
local prefab_component_storage = prefab_component_storages[prefab_component_index] local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place] ini_component = prefab_component_storage[prefab_place]
else
ini_component = chunk_component_defaults[component_index]
end
end
end
if fragment_duplicate then if ini_component ~= nil and component_duplicate then
for place = b_place, e_place do for place = b_place, e_place do
local new_component = prefab_component local new_component = component_duplicate(ini_component)
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end if new_component == nil then
new_component = true
end
component_storage[place] = new_component component_storage[place] = new_component
end end
else else
local new_component = prefab_component if ini_component == nil then
if new_component == nil then new_component = true end ini_component = true
end
for place = b_place, e_place do for place = b_place, e_place do
component_storage[place] = new_component component_storage[place] = ini_component
end
end
end
end
else
for prefab_component_index = 1, prefab_component_count do
local fragment = prefab_component_fragments[prefab_component_index]
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local prefab_component_storage = prefab_component_storages[prefab_component_index]
local prefab_component = prefab_component_storage[prefab_place]
local new_component = prefab_component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
end
end
if chunk.__has_setup_hooks then
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
---@type evolved.duplicate?
local fragment_duplicate =
__evolved_get(fragment, __DUPLICATE)
if fragment_duplicate then
for place = b_place, e_place do
local new_component = component
if new_component ~= nil then new_component = fragment_duplicate(new_component) end
if new_component == nil then new_component = true end
component_storage[place] = new_component
end
else
local new_component = component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
---@type evolved.default?, evolved.duplicate?
local req_fragment_default, req_fragment_duplicate =
__evolved_get(req_fragment, __DEFAULT, __DUPLICATE)
if req_fragment_duplicate then
for place = b_place, e_place do
local req_component = req_fragment_default
if req_component ~= nil then req_component = req_fragment_duplicate(req_component) end
if req_component == nil then req_component = true end
req_component_storage[place] = req_component
end
else
local req_component = req_fragment_default
if req_component == nil then req_component = true end
for place = b_place, e_place do
req_component_storage[place] = req_component
end
end
end
end
end
else
for fragment, component in __lua_next, components do
local component_index = chunk_component_indices[fragment]
if component_index then
local component_storage = chunk_component_storages[component_index]
local new_component = component
if new_component == nil then new_component = true end
for place = b_place, e_place do
component_storage[place] = new_component
end
end
end
for req_fragment_index = 1, req_fragment_count do
local req_fragment = req_fragment_list[req_fragment_index]
if ini_fragment_set[req_fragment] then
-- this fragment has already been initialized
else
local req_component_index = chunk_component_indices[req_fragment]
if req_component_index then
local req_component_storage = chunk_component_storages[req_component_index]
local req_component = true
for place = b_place, e_place do
req_component_storage[place] = req_component
end
end
end end
end end
end end
@@ -2887,12 +2587,12 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
local fragment_on_set, fragment_on_insert = local fragment_on_set, fragment_on_insert =
__evolved_get(fragment, __ON_SET, __ON_INSERT) __evolved_get(fragment, __ON_SET, __ON_INSERT)
if fragment_on_set or fragment_on_insert then
local component_index = chunk_component_indices[fragment] local component_index = chunk_component_indices[fragment]
if component_index then if component_index then
local component_storage = chunk_component_storages[component_index] local component_storage = chunk_component_storages[component_index]
if fragment_on_set or fragment_on_insert then
for place = b_place, e_place do for place = b_place, e_place do
local entity = chunk_entity_list[place] local entity = chunk_entity_list[place]
@@ -2907,10 +2607,6 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
end end
end end
else else
-- nothing
end
else
if fragment_on_set or fragment_on_insert then
for place = b_place, e_place do for place = b_place, e_place do
local entity = chunk_entity_list[place] local entity = chunk_entity_list[place]
@@ -2922,8 +2618,6 @@ function __multi_clone_entity(prefab, entity_list, entity_count, components)
fragment_on_insert(entity, fragment) fragment_on_insert(entity, fragment)
end end
end end
else
-- nothing
end end
end end
end end
@@ -5464,7 +5158,6 @@ function __evolved_execute(query)
local query_excludes = __sorted_excludes[query] local query_excludes = __sorted_excludes[query]
local query_exclude_set = query_excludes and query_excludes.__item_set local query_exclude_set = query_excludes and query_excludes.__item_set
local query_exclude_list = query_excludes and query_excludes.__item_list
local query_exclude_count = query_excludes and query_excludes.__item_count or 0 local query_exclude_count = query_excludes and query_excludes.__item_count or 0
if query_include_count > 0 then if query_include_count > 0 then
@@ -5483,7 +5176,7 @@ function __evolved_execute(query)
for _, root_chunk in __lua_next, __root_chunks do for _, root_chunk in __lua_next, __root_chunks do
local is_root_chunk_matched = local is_root_chunk_matched =
not root_chunk.__has_explicit_fragments and not root_chunk.__has_explicit_fragments and
not __chunk_has_any_fragment_list(root_chunk, query_exclude_list, query_exclude_count) not query_exclude_set[root_chunk.__fragment]
if is_root_chunk_matched then if is_root_chunk_matched then
chunk_stack_size = chunk_stack_size + 1 chunk_stack_size = chunk_stack_size + 1
@@ -6184,7 +5877,7 @@ function __builder_mt:internal()
return self:set(__INTERNAL) return self:set(__INTERNAL)
end end
---@param default evolved.component ---@param default evolved.default
---@return evolved.builder builder ---@return evolved.builder builder
function __builder_mt:default(default) function __builder_mt:default(default)
return self:set(__DEFAULT, default) return self:set(__DEFAULT, default)

10
example/conf.lua Normal file
View File

@@ -0,0 +1,10 @@
if os.getenv('LOCAL_LUA_DEBUGGER_VSCODE') == '1' then
require('lldebugger').start()
end
---@type love.conf
function love.conf(t)
t.window.title = 'Evolved Example'
t.window.width = 640
t.window.height = 480
end

173
example/main.lua Normal file
View File

@@ -0,0 +1,173 @@
local evolved = require 'evolved'
local STAGES = {
ON_SETUP = evolved.builder()
:name('STAGES.ON_SETUP')
:build(),
ON_UPDATE = evolved.builder()
:name('STAGES.ON_UPDATE')
:build(),
ON_RENDER = evolved.builder()
:name('STAGES.ON_RENDER')
:build(),
}
local UNIFORMS = {
DELTA_TIME = 1.0 / 60.0,
}
local FRAGMENTS = {
POSITION_X = evolved.builder()
:name('FRAGMENTS.POSITION_X')
:default(0)
:build(),
POSITION_Y = evolved.builder()
:name('FRAGMENTS.POSITION_Y')
:default(0)
:build(),
VELOCITY_X = evolved.builder()
:name('FRAGMENTS.VELOCITY_X')
:default(0)
:build(),
VELOCITY_Y = evolved.builder()
:name('FRAGMENTS.VELOCITY_Y')
:default(0)
:build(),
}
local PREFABS = {
CIRCLE = evolved.builder()
:name('PREFABS.CIRCLE')
:prefab()
:set(FRAGMENTS.POSITION_X)
:set(FRAGMENTS.POSITION_Y)
:set(FRAGMENTS.VELOCITY_X)
:set(FRAGMENTS.VELOCITY_Y)
:build(),
}
---
---
---
---
---
evolved.builder()
:name('SYSTEMS.STARTUP')
:group(STAGES.ON_SETUP)
:prologue(function()
local screen_width, screen_height = love.graphics.getDimensions()
local circle_list, circle_count = evolved.multi_clone(100, PREFABS.CIRCLE)
for i = 1, circle_count do
local circle = circle_list[i]
local px = math.random() * screen_width
local py = math.random() * screen_height
local vx = math.random(-100, 100)
local vy = math.random(-100, 100)
evolved.set(circle, FRAGMENTS.POSITION_X, px)
evolved.set(circle, FRAGMENTS.POSITION_Y, py)
evolved.set(circle, FRAGMENTS.VELOCITY_X, vx)
evolved.set(circle, FRAGMENTS.VELOCITY_Y, vy)
end
end):build()
evolved.builder()
:name('SYSTEMS.MOVEMENT')
:group(STAGES.ON_UPDATE)
:include(FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
:include(FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
:execute(function(chunk, _, entity_count)
local delta_time = UNIFORMS.DELTA_TIME
local screen_width, screen_height = love.graphics.getDimensions()
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
---@type number[], number[]
local velocity_xs, velocity_ys = chunk:components(
FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
for i = 1, entity_count do
local px, py = position_xs[i], position_ys[i]
local vx, vy = velocity_xs[i], velocity_ys[i]
px = px + vx * delta_time
py = py + vy * delta_time
if px < 0 and vx < 0 then
vx = -vx
elseif px > screen_width and vx > 0 then
vx = -vx
end
if py < 0 and vy < 0 then
vy = -vy
elseif py > screen_height and vy > 0 then
vy = -vy
end
position_xs[i], position_ys[i] = px, py
velocity_xs[i], velocity_ys[i] = vx, vy
end
end):build()
evolved.builder()
:name('SYSTEMS.RENDERING')
:group(STAGES.ON_RENDER)
:include(FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
:execute(function(chunk, _, entity_count)
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
for i = 1, entity_count do
local x, y = position_xs[i], position_ys[i]
love.graphics.circle('fill', x, y, 10)
end
end):build()
evolved.builder()
:name('SYSTEMS.DEBUGGING')
:group(STAGES.ON_RENDER)
:epilogue(function()
local fps = love.timer.getFPS()
local mem = collectgarbage('count')
love.graphics.print(string.format('FPS: %d', fps), 10, 10)
love.graphics.print(string.format('MEM: %d KB', mem), 10, 30)
end):build()
---
---
---
---
---
---@type love.load
function love.load()
evolved.process(STAGES.ON_SETUP)
end
---@type love.update
function love.update(dt)
UNIFORMS.DELTA_TIME = dt
evolved.process(STAGES.ON_UPDATE)
end
---@type love.draw
function love.draw()
evolved.process(STAGES.ON_RENDER)
end
---@type love.keypressed
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
end

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.5.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.5.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}