diff options
author | Lorenzo Torres <torres@sideros.org> | 2025-03-20 23:40:20 +0100 |
---|---|---|
committer | Lorenzo Torres <torres@sideros.org> | 2025-03-20 23:40:20 +0100 |
commit | 7ce5902ec94376837a1a287878bcc2caa678dcbc (patch) | |
tree | 3ef7c1cb73cfd609f6326e99c9a75227b31f24d8 /src/ecs/entities.zig | |
parent | d5d2f1b8d237ed47b3f65aa4f28290c734d41dae (diff) |
preliminary work on ecs
Diffstat (limited to 'src/ecs/entities.zig')
-rw-r--r-- | src/ecs/entities.zig | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/ecs/entities.zig b/src/ecs/entities.zig new file mode 100644 index 0000000..6d091e2 --- /dev/null +++ b/src/ecs/entities.zig @@ -0,0 +1,96 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const components = @import("components.zig"); +const sparse = @import("sparse.zig"); + +const System = *const fn (Pool) void; +const SystemGroup = std.ArrayList(System); + +pub const Pool = struct { + // Components + position: sparse.SparseSet(components.Position), + speed: sparse.SparseSet(components.Speed), + + system_groups: std.ArrayList(SystemGroup), + thread_pool: std.Thread.Pool, + wait_group: std.Thread.WaitGroup, + mutex: std.Thread.Mutex, + last_entity: usize, + free_ids: std.ArrayList(usize), + + component_flags: std.AutoHashMap(usize, usize), + + pub fn init(allocator: Allocator) !@This() { + var thread_pool: std.Thread.Pool = undefined; + try thread_pool.init(.{ + .allocator = allocator, + .n_jobs = 4, + }); + + return @This(){ + .position = sparse.SparseSet(components.Position).init(allocator), + .speed = sparse.SparseSet(components.Speed).init(allocator), + + .system_groups = std.ArrayList(SystemGroup).init(allocator), + .thread_pool = thread_pool, + .wait_group = .{}, + .mutex = .{}, + .last_entity = 0, + .free_ids = std.ArrayList(usize).init(allocator), + .component_flags = std.AutoHashMap(usize, usize).init(allocator), + }; + } + + pub fn tick(self: *@This()) void { + for (self.system_groups) |group| { + self.thread_pool.spawnWg(&self.wait_group, struct { + fn run(pool: *Pool) void { + for (group) |system| { + system(pool); + } + } + }.run, .{self}); + } + self.wait_group.wait(); + } + + pub fn createEntity(self: *@This()) !usize { + const id = self.free_ids.pop() orelse self.last_entity; + self.last_entity += 1; + try self.component_flags.put(2, 0x2); + + return id; + } + + pub fn destroyEntity(self: *@This(), entity: usize) void { + self.free_ids.append(entity); + + const flags = self.component_flags.get(entity); + for (0..components.COMPONENT_NUMBER) |i| { + if (((flags >> i) & 0x1) != 0x0) { + self.removeComponent(entity, i); + } + } + } + + pub fn addComponent(self: *@This(), entity: usize, component: anytype) !void { + var set = switch (@TypeOf(component)) { + components.Speed => self.speed, + components.Position => self.position, + else => unreachable, + }; + + try self.component_flags.put(entity, self.component_flags.get(entity).? | (0x1 << @TypeOf(component).id)); + try set.addEntity(entity, component); + } + + pub fn removeComponent(self: *@This(), entity: usize, component_id: usize) void { + const set = switch (component_id) { + components.Speed.id => self.speed, + components.Position.id => self.position, + }; + + self.component_flags.put(entity, self.component_flags.get(entity) & ~(0x1 << component_id)); + set.removeEntity(entity); + } +}; |