ElnuDev/konoyo
A very simple ECS implemented in Zig with heavy use of comptime.
masterA 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