diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ecs/component.zig | 39 | ||||
-rw-r--r-- | src/ecs/ecs.zig | 84 | ||||
-rw-r--r-- | src/ecs/entity.zig | 45 | ||||
-rw-r--r-- | src/root.zig | 6 |
4 files changed, 127 insertions, 47 deletions
diff --git a/src/ecs/component.zig b/src/ecs/component.zig new file mode 100644 index 0000000..4a10172 --- /dev/null +++ b/src/ecs/component.zig @@ -0,0 +1,39 @@ +const std = @import("std"); + +pub const ComponentStub = struct { + pub fn init(args: ComponentStub) ComponentStub { + _ = args; + return .{}; + } + + pub fn deinit(self: *ComponentStub) void { + _ = self; + } +}; + +pub const ComponentType = enum(usize) { + component_stub = 0, +}; + +pub const Component = union(ComponentType) { + component_stub: ComponentStub, + + pub fn init(t: ComponentType, args: anytype) Component { + switch (t) { + ComponentType.component_stub => return Component{ + .component_stub = ComponentStub.init(args), + }, + } + } + + pub fn deinit(self: *Component) void { + switch (self.*) { + .component_stub => |*comp| comp.deinit(), + } + } +}; + +test "stub component" { + var stub = Component.init(ComponentType.component_stub, .{}); + defer stub.deinit(); +} 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, .{}); +} diff --git a/src/ecs/entity.zig b/src/ecs/entity.zig deleted file mode 100644 index 2ad8556..0000000 --- a/src/ecs/entity.zig +++ /dev/null @@ -1,45 +0,0 @@ -const std = @import("std"); - -pub const Entity = struct { - id: usize, -}; - -pub const EntityCollection = struct { - allocator: std.mem.Allocator, - next_id: usize, - entities: std.AutoHashMap(usize, Entity), - - pub fn addEntity(self: *EntityCollection) !usize { - try self.entities.put(self.next_id, .{ - .id = self.next_id, - }); - - self.next_id += 1; - - return self.next_id - 1; - } - - pub fn init(allocator: std.mem.Allocator) EntityCollection { - return .{ - .allocator = allocator, - .next_id = 0, - .entities = std.AutoHashMap(usize, Entity).init(allocator), - }; - } - - pub fn deinit(self: *EntityCollection) void { - self.entities.deinit(); - } -}; - -test "create entities" { - try std.testing.expect(true); - - var ec = EntityCollection.init(std.testing.allocator); - defer ec.deinit(); - - for (0..128) |i| { - const id = ec.addEntity(); - try std.testing.expectEqual(i, id); - } -} diff --git a/src/root.zig b/src/root.zig index 62b3398..330b6ba 100644 --- a/src/root.zig +++ b/src/root.zig @@ -1,8 +1,10 @@ const std = @import("std"); const testing = std.testing; -const entity = @import("ecs/entity.zig"); +const component = @import("ecs/component.zig"); +const ecs = @import("ecs/ecs.zig"); test { - _ = entity; + _ = component; + _ = ecs; } |