From 900c8756edc3bc547dfd2cd47921ecd453bf703b Mon Sep 17 00:00:00 2001 From: jjanzen Date: Tue, 21 Jan 2025 23:26:23 -0600 Subject: doc comments and io refactor --- src/ecs/component.zig | 4 ++++ src/ecs/ecs.zig | 39 +++++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 12 deletions(-) (limited to 'src/ecs') diff --git a/src/ecs/component.zig b/src/ecs/component.zig index 37956d0..3a50c88 100644 --- a/src/ecs/component.zig +++ b/src/ecs/component.zig @@ -1,5 +1,7 @@ +//! This module provides a basic component interface for an Entity Component System const std = @import("std"); +/// An empty component for testing purposes pub const ComponentStub = struct { pub fn init(args: ComponentStub) ComponentStub { _ = args; @@ -11,10 +13,12 @@ pub const ComponentStub = struct { } }; +/// All valid component types are stored in this enum pub const ComponentType = enum { component_stub, }; +/// The components are stored as a MultiArrayList over this struct pub const Components = struct { component_stub: ?ComponentStub, }; diff --git a/src/ecs/ecs.zig b/src/ecs/ecs.zig index d1341bf..47c576b 100644 --- a/src/ecs/ecs.zig +++ b/src/ecs/ecs.zig @@ -1,12 +1,20 @@ +//! This module provides an implementation of an Entity Component System const std = @import("std"); const component = @import("component.zig"); const ComponentType = component.ComponentType; +/// EntityComponentSystem keeps track of components in a MultiArrayList of Components. +/// Each Entity is simply an index into that MultiArrayList of Components. +/// To save on memory and avoid resizing, ids are recycled upon Entities being deleted. pub const EntityComponentSystem = struct { + /// An allocator for use by the EntityComponentSystem to manage memory allocator: std.mem.Allocator, + + /// The mapping of Components to Entities is in this MultiArrayList components: std.MultiArrayList(component.Components), + + /// Keeps track of ids available for reuse available_ids: std.ArrayList(usize), - next_id: usize, fn nullEntity(self: *EntityComponentSystem, entity: usize) void { inline for (std.enums.valuesFromFields(ComponentType, std.meta.fields(ComponentType))) |comp| { @@ -19,7 +27,6 @@ pub const EntityComponentSystem = struct { .allocator = allocator, .components = .{}, .available_ids = std.ArrayList(usize).init(allocator), - .next_id = 0, }; } @@ -28,28 +35,34 @@ pub const EntityComponentSystem = struct { self.components.deinit(self.allocator); } + /// Create a new entity (or recycle an old one) and return the id. + /// May error if the Allocator runs out of memory. pub fn createEntity(self: *EntityComponentSystem) !usize { const id = self.available_ids.popOrNull() orelse noroom: { - const id = self.next_id; + const id = self.components.len; try self.components.append(self.allocator, undefined); - self.next_id += 1; break :noroom id; }; self.nullEntity(id); return id; } + /// Add an entity to a component. + /// Takes a ComponentType and an entity id along with any arguments needed to initialize the component. pub fn componentAddEntity( self: *EntityComponentSystem, comp: component.ComponentType, entity: usize, args: anytype, - ) !void { + ) void { switch (comp) { ComponentType.component_stub => self.components.items(.component_stub)[entity] = component.ComponentStub.init(args), } } + /// Delete an entity and make it ready for recycling by nulling all components. + /// Takes an entity id. + /// May error if the Allocator runs out of memory. pub fn deleteEntity(self: *EntityComponentSystem, entity: usize) !void { self.nullEntity(entity); try self.available_ids.append(entity); @@ -61,6 +74,8 @@ pub const EntityComponentSystem = struct { comp[entity] = null; } + /// Removes an entity from a component. + /// Takes a ComponentType and an entity id. pub fn componentRemoveEntity( self: *EntityComponentSystem, comp: component.ComponentType, @@ -80,7 +95,7 @@ test "add entities to components" { for (0..100) |i| { const entity = try ecs.createEntity(); try std.testing.expectEqual(i, entity); - try ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); try std.testing.expect(ecs.components.items(.component_stub)[entity] != null); } } @@ -90,9 +105,9 @@ test "remove entities from components" { defer ecs.deinit(); const entity = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); const entity2 = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); try std.testing.expect(ecs.components.items(.component_stub)[entity2] != null); ecs.componentRemoveEntity(ComponentType.component_stub, entity2); @@ -104,9 +119,9 @@ test "delete entities" { defer ecs.deinit(); const entity = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); const entity2 = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); try std.testing.expect(ecs.components.items(.component_stub)[entity2] != null); try ecs.deleteEntity(entity2); @@ -119,9 +134,9 @@ test "recycle entities" { defer ecs.deinit(); const entity = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity, .{}); const entity2 = try ecs.createEntity(); - try ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); + ecs.componentAddEntity(ComponentType.component_stub, entity2, .{}); try ecs.deleteEntity(entity2); try std.testing.expectEqual(1, ecs.available_ids.items.len); -- cgit v1.2.3