From 6cd699efbc4b3b78e1b417aedaf5355a4a996b9d Mon Sep 17 00:00:00 2001 From: copygirl Date: Tue, 9 May 2023 13:36:47 +0200 Subject: [PATCH] Update README --- README.md | 57 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 02fe46e..347251b 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # 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. +.. 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. + +These classes have been split from the main [gæmstone] project. It is still a little unclear what functionality belongs where, and structural changes may occur. In its current state, I recommend to use this repository simply as a reference for building similar projects. [ECS]: https://en.wikipedia.org/wiki/Entity_component_system [Flecs]: https://github.com/SanderMertens/flecs @@ -13,20 +11,18 @@ is required. ## 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]. +- Convenient wrapper types such as [Identifier], [Entity] and [EntityType]. - [EntityPath] uses a unix-like path, for example `/Game/Players/copygirl`. +- Fast type-to-entity lookup using generic context on [World]. (See below.) - 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 +[Entity]: ./src/gaemstone.ECS/Entity.cs [EntityType]: ./src/gaemstone.ECS/EntityType.cs [EntityPath]: ./src/gaemstone.ECS/EntityPath.cs +[World]: ./src/gaemstone.ECS/World.cs [Components]: ./src/gaemstone.ECS/Component.cs [Iterators]: ./src/gaemstone.ECS/Iterator.cs [Filters]: ./src/gaemstone.ECS/Filter.cs @@ -38,7 +34,7 @@ These classes have only recently been split from the main **gæmstone** project. ## Example ```cs -var world = new World(); +var world = new World(); var position = world .New("Position") // Create a new EntityBuilder, and set its name. @@ -55,26 +51,31 @@ 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(); - pos = new(pos.X * 10, pos.Y * 10); + ref var pos = ref child.GetRefOrThrow(); + pos = new(pos.X * 10, pos.Y * 10); } -var onUpdate = world.LookupByPathOrThrow("/flecs/pipeline/OnUpdate"); +// The following systems run in the "OnUpdate" +// phase of the default pipeline provided by Flecs. +var dependsOn = world.LookupPathOrThrow("/flecs/core/DependsOn"); +var onUpdate = world.LookupPathOrThrow("/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 => { +world.New("FallSystem") + .Add(dependsOn, onUpdate) + .Build().InitSystem(new("Position"), iter => { var posColumn = iter.Field(1); for (var i = 0; i < iter.Count; i++) { ref var pos = ref posColumn[i]; - pos = new(pos.X, pos.Y + 2); + 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 => { + .Add(dependsOn, onUpdate) + .InitSystem(new("[in] Position"), iter => { var posColumn = iter.Field(1); for (var i = 0; i < iter.Count; i++) { var entity = iter.Entity(i); @@ -109,3 +110,21 @@ dotnet add reference gaemstone.ECS/gaemstone.ECS.csproj # To generate flecs-cs' bindings: ./gaemstone.ECS/src/flecs-cs/library.sh ``` + +## On the `TContext` type parameter + +Entities may be looked up simply by their type, once they're registered with `CreateLookup` or `InitComponent`. Under the hood, this is made possible using a nested static generic class that hold onto an `Entity` field. Theoretically this could be compiled into a simple field lookup and therefore be faster than dictionary lookups. + +To support scenarios where multiple worlds may be used simultaneously, each with their own unique type lookups, we specify a generic type as that context. + +In cases where only a single world is used, the amount of typing can be reduced by including a file similar to the following, defining global aliases: + +```cs +global using Entity = gaemstone.ECS.Entity; +global using Id = gaemstone.ECS.Id; +global using Iterator = gaemstone.ECS.Iterator; +global using World = gaemstone.ECS.World; +// Add more aliases as you feel they are needed. + +public struct Context { } +```