From 8a20d05a7a8cf9f1339142240907ed158449dfa0 Mon Sep 17 00:00:00 2001 From: jjanzen Date: Tue, 21 Jan 2025 19:20:50 -0600 Subject: add basic entity component system --- src/ecs/ecs.zig | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/ecs/ecs.zig (limited to 'src/ecs/ecs.zig') 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, .{}); +} -- cgit v1.2.3