You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.2 KiB
111 lines
4.2 KiB
# gaemstone.ECS |
|
|
|
.. is a medium-level managed wrapper library around the [flecs-cs] bindings |
|
for the amazing [Entity Component System (ECS)][ECS] framework [Flecs]. It is |
|
used as part of the [gæmstone] game engine, but may be used in other projects |
|
as well. To efficiently use this library, a thorough understanding of [Flecs] |
|
is required. |
|
|
|
[ECS]: https://en.wikipedia.org/wiki/Entity_component_system |
|
[Flecs]: https://github.com/SanderMertens/flecs |
|
[flecs-cs]: https://github.com/flecs-hub/flecs-cs |
|
[gæmstone]: https://git.mcft.net/copygirl/gaemstone |
|
|
|
## Features |
|
|
|
These classes have only recently been split from the main **gæmstone** project. It is currently unclear what functionality belongs where, and structural changes are still very likely. In its current state, feel free to use **gæmstone.ECS** as a reference for building similar projects, or be aware that things are in flux, and in general nowhere near stable. |
|
|
|
- Simple wrapper structs such as [Entity] and [Identifier]. |
|
- Classes with convenience functions like [EntityRef] and [EntityType]. |
|
- [EntityPath] uses a unix-like path, for example `/Game/Players/copygirl`. |
|
- Define your own [Components] as both value or reference types. |
|
- Query the ECS with [Iterators], [Filters], [Queries] and [Rules]. |
|
- Create [Systems] for game logic and [Observers] to act on changes. |
|
|
|
[Entity]: ./src/gaemstone.ECS/Entity.cs |
|
[Identifier]: ./src/gaemstone.ECS/Identifier.cs |
|
[EntityRef]: ./src/gaemstone.ECS/EntityRef.cs |
|
[EntityType]: ./src/gaemstone.ECS/EntityType.cs |
|
[EntityPath]: ./src/gaemstone.ECS/EntityPath.cs |
|
[Components]: ./src/gaemstone.ECS/Component.cs |
|
[Iterators]: ./src/gaemstone.ECS/Iterator.cs |
|
[Filters]: ./src/gaemstone.ECS/Filter.cs |
|
[Queries]: ./src/gaemstone.ECS/Query.cs |
|
[Rules]: ./src/gaemstone.ECS/Rule.cs |
|
[Systems]: ./src/gaemstone.ECS/System.cs |
|
[Observers]: ./src/gaemstone.ECS/Observer.cs |
|
|
|
## Example |
|
|
|
```cs |
|
var world = new World(); |
|
|
|
var position = world |
|
.New("Position") // Create a new EntityBuilder, and set its name. |
|
.Symbol("Position") // Set entity's symbol. (Used in query expression.) |
|
.Build() // Actually create the entity in-world. |
|
// Finally, create a component from this entity. |
|
// "Position" is defined at the bottom of this example. |
|
.InitComponent<Position>(); |
|
|
|
// Create an "Entities" parent with two positioned entities inside. |
|
var entities = world.New("Entities").Build(); |
|
entities.NewChild("One").Set(new Position(-5, 0)).Build(); |
|
entities.NewChild("Two").Set(new Position(10, 20)).Build(); |
|
|
|
// Changed my mind: Let's multiply each entity's position by 10. |
|
foreach (var child in entities.GetChildren()) { |
|
ref var pos = ref child.GetRefOrThrow<Position>(); |
|
pos = new(pos.X * 10, pos.Y * 10); |
|
} |
|
|
|
var onUpdate = world.LookupByPathOrThrow("/flecs/pipeline/OnUpdate"); |
|
|
|
// Create a system that will move all entities with |
|
// the "Position" component downwards by 2 every frame. |
|
world.New("FallSystem").Build() |
|
.InitSystem(onUpdate, new("Position"), iter => { |
|
var posColumn = iter.Field<Position>(1); |
|
for (var i = 0; i < iter.Count; i++) { |
|
ref var pos = ref posColumn[i]; |
|
pos = new(pos.X, pos.Y + 2); |
|
} |
|
}); |
|
|
|
// Create a system that will print out entities' positions. |
|
world.New("PrintPositionSystem").Build() |
|
.InitSystem(onUpdate, new("[in] Position"), iter => { |
|
var posColumn = iter.Field<Position>(1); |
|
for (var i = 0; i < iter.Count; i++) { |
|
var entity = iter.Entity(i); |
|
var pos = posColumn[i]; |
|
Console.WriteLine($"{entity.Name} is at {pos}"); |
|
} |
|
}); |
|
|
|
// Infinite loop that runs the "game" at 30 FPS. |
|
while (true) { |
|
var delta = TimeSpan.FromSeconds(1.0f / 30); |
|
// Progress returns false if quit was requested. |
|
if (!world.Progress(delta)) break; |
|
Thread.Sleep(delta); |
|
} |
|
|
|
record struct Position(int X, int Y); |
|
``` |
|
|
|
## Instructions |
|
|
|
```sh |
|
# Clone the repository. Recurse into submodules to include flecs-cs and flecs. |
|
git clone --recurse-submodules https://git.mcft.net/copygirl/gaemstone.ECS.git |
|
|
|
# If you want to add it to your own repository as a submodule: |
|
git submodule add https://git.mcft.net/copygirl/gaemstone.ECS.git |
|
|
|
# To add a reference to this library to your .NET project: |
|
dotnet add reference gaemstone.ECS/gaemstone.ECS.csproj |
|
|
|
# To generate flecs-cs' bindings: |
|
./gaemstone.ECS/src/flecs-cs/library.sh |
|
```
|
|
|