ElnuDev/konoyo
A very simple ECS implemented in Zig with heavy use of comptime.
master
A very simple ECS implemented in Zig with heavy use of comptime. Doesn't do anything fancy like archetypes.
To run the raylib exmaple, run zig build -Dexample run
.
To get started, import konoyo and initialize an ECS world type definition with a component list.
Component types must meet the following requirements:
Once you have declared your world type, you can initialize it with an allocator. For each of the provided components, konoyo internally stores a hash table mapping from a u32
entity ID to component instances.
Supposing you have already defined a TransformComponent
and SpriteComponent
(the ones used here are the same in the example), you can set up konoyo as follows.
const std = @import("std");
const ecs = @import("konoyo");
const World = ecs.World(&[_]type{
TransformComponent,
SpriteComponent,
});
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var world = World.init(allocator);
defer world.deinit();
To create an entity, call world.createEntity
. This will return a unique ID for the created entity.
const entity = world.createEntity();
You can then add any component that was defined in the world definition.
world.insert(entity, TransformComponent {
...
});
world.insert(entity, SpriteComponent {
...
});
To query the world, call world.query
, passing in a query slice of types you want your query to return. The query will return an array list of QueryResult(Query)
. Each query result will contain an entity
field with the entity ID and one field for each type in your query, e.g. querying for a TransformComponent
will give you a transform
field in every query result.
const Query = &[_]type{ *TransformComponent, *const SpriteComponent };
const results = world.query(query);
defer world.allocator.free(results);
for (results) |e| {
std.debug.print("Entity ID: {}\n", .{ e.entity });
e.transform.position.x += 42;
e.sprite.draw(e.transform.position);
}
Optional components are also supported.
const Query = &[_]type{ *TransformComponent, ?*const SpriteComponent };
Queried types are immutable by default: Component
is a valid shorthand for *const Component
.
const Query = &[_]type{ *TransformComponent, ?SpriteComponent };
// get total number of components with given component
_ = world.count(SpriteComponent);
const entity = 0;
// deleteEntity returns whether or not the entity existed to begin with
_ = world.deleteEntity(entity);
// delete returns whether or not the component existed to begin with
_ = world.delete(entity, TransformComponent);
// check if entity exists
_ = world.entityExists(entity);
Reimu fumo sprite by Jaysa under CC0 via OpenGameArt.org