aboutsummaryrefslogtreecommitdiff
path: root/src/ecs/ecs.zig
diff options
context:
space:
mode:
authorjjanzen <jjanzen@jjanzen.ca>2025-01-21 19:20:50 -0600
committerjjanzen <jjanzen@jjanzen.ca>2025-01-21 19:20:50 -0600
commit8a20d05a7a8cf9f1339142240907ed158449dfa0 (patch)
treebabbf74a7bea83589b05f117a795235deb0e238c /src/ecs/ecs.zig
parent9f18b702b15b4a26a016170a8a2dfb216ae15810 (diff)
add basic entity component system
Diffstat (limited to 'src/ecs/ecs.zig')
-rw-r--r--src/ecs/ecs.zig84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/ecs/ecs.zig b/src/ecs/ecs.zig
new file mode 100644
index 0000000..542de34
--- /dev/null
+++ b/src/ecs/ecs.zig
@@ -0,0 +1,84 @@
+const std = @import("std");
+const component = @import("component.zig");
+
+const ComponentList = struct {
+ entities: std.AutoHashMap(usize, component.Component),
+};
+
+pub const EntityComponentSystem = struct {
+ entities: std.ArrayList(usize),
+ components: std.AutoHashMap(usize, ComponentList),
+ available_ids: std.ArrayList(usize),
+ next_id: usize,
+
+ pub fn init(allocator: std.mem.Allocator) !EntityComponentSystem {
+ var ecs = EntityComponentSystem{
+ .entities = std.ArrayList(usize).init(allocator),
+ .components = std.AutoHashMap(usize, ComponentList).init(allocator),
+ .available_ids = std.ArrayList(usize).init(allocator),
+ .next_id = 0,
+ };
+
+ inline for (std.meta.fields(component.ComponentType)) |comp| {
+ try ecs.components.put(comp.value, ComponentList{
+ .entities = std.AutoHashMap(usize, component.Component).init(allocator),
+ });
+ }
+
+ return ecs;
+ }
+
+ pub fn deinit(self: *EntityComponentSystem) void {
+ self.entities.deinit();
+ self.available_ids.deinit();
+
+ var component_iterator = self.components.iterator();
+ while (component_iterator.next()) |component_entry| {
+ var comp = component_entry.value_ptr;
+
+ var entity_iterator = comp.entities.iterator();
+ while (entity_iterator.next()) |entity_entry| {
+ var entity = entity_entry.value_ptr;
+
+ entity.deinit();
+ }
+
+ comp.entities.deinit();
+ }
+ self.components.deinit();
+ }
+
+ pub fn createEntity(self: *EntityComponentSystem) !usize {
+ const reuse_id = self.available_ids.popOrNull();
+ if (reuse_id != null and reuse_id.? < self.entities.items.len) {
+ self.entities.items[reuse_id.?] = reuse_id.?;
+ return reuse_id.?;
+ }
+
+ const id = self.next_id;
+ try self.entities.append(id);
+ self.next_id += 1;
+ return id;
+ }
+
+ pub fn componentAddEntity(
+ self: *EntityComponentSystem,
+ comp: component.ComponentType,
+ entity: usize,
+ args: anytype,
+ ) !void {
+ var comp_list = self.components.getPtr(@intFromEnum(comp)) orelse return;
+
+ try comp_list.entities.put(entity, component.Component.init(comp, args));
+ }
+};
+
+test "add entities to components" {
+ var ecs = try EntityComponentSystem.init(std.testing.allocator);
+ defer ecs.deinit();
+
+ const entity = try ecs.createEntity();
+ try std.testing.expectEqual(0, entity);
+
+ try ecs.componentAddEntity(component.ComponentType.component_stub, entity, .{});
+}