Components
This commit is contained in:
89
src/components.zig
Normal file
89
src/components.zig
Normal file
@@ -0,0 +1,89 @@
|
||||
const std = @import("std");
|
||||
const err = @import("error.zig");
|
||||
const Game = @import("game.zig");
|
||||
|
||||
pub const StorageOptions = struct {
|
||||
min_capacity: usize = 32,
|
||||
};
|
||||
|
||||
pub fn Storage(comptime T: type, comptime options: StorageOptions) type {
|
||||
return struct {
|
||||
pub const Key = packed struct {
|
||||
cell: u32,
|
||||
version: u32,
|
||||
};
|
||||
pub const MIN_CAPACITY = options.min_capacity;
|
||||
|
||||
const Array = std.ArrayListUnmanaged;
|
||||
const Cell = struct {
|
||||
component: T,
|
||||
version: u32,
|
||||
count: u32,
|
||||
};
|
||||
|
||||
components: Array(Cell),
|
||||
|
||||
const Self = @This();
|
||||
pub fn init() Self {
|
||||
return .{
|
||||
.components = Array(Cell).empty,
|
||||
};
|
||||
}
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.components.deinit(Game.alloc);
|
||||
}
|
||||
pub fn add(self: *Self, component: T) Key {
|
||||
for (0.., self.components.items) |i, *cell| {
|
||||
if (cell.count == 0) {
|
||||
return populateCell(cell, i, component);
|
||||
}
|
||||
}
|
||||
const cell = self.components.addOne(Game.alloc) catch err.oom();
|
||||
return populateCell(cell, self.components.items.len - 1, component);
|
||||
}
|
||||
pub fn lock(self: *Self, key: Key) void {
|
||||
self.components.items[key.cell].count += 1;
|
||||
}
|
||||
pub fn get(self: *Self, key: Key) ?*T {
|
||||
const cell = &self.components.items[key.cell];
|
||||
if (cell.version == key.version) {
|
||||
return &cell.component;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
pub fn free(self: *Self, key: Key) bool {
|
||||
self.components.items[key.cell].count -= 1;
|
||||
}
|
||||
pub fn iter(self: *Self) Iterator {
|
||||
return .{
|
||||
.array = self.components.items,
|
||||
.current = 0,
|
||||
};
|
||||
}
|
||||
|
||||
fn populateCell(cell: *Cell, index: usize, component: T) Key {
|
||||
cell.version += 1;
|
||||
cell.count = 1;
|
||||
cell.component = component;
|
||||
return .{
|
||||
.cell = @intCast(index),
|
||||
.version = cell.version,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Iterator = struct {
|
||||
array: []Cell,
|
||||
current: usize,
|
||||
|
||||
pub fn next(self: *@This()) ?*T {
|
||||
while (self.current < self.array.len) {
|
||||
defer self.current += 1;
|
||||
if (self.array[self.current].count != 0) {
|
||||
return &self.array[self.current].component;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
@@ -13,7 +13,7 @@ const Time = struct {
|
||||
now: sdl.Time,
|
||||
};
|
||||
|
||||
var alloc: std.mem.Allocator = undefined;
|
||||
pub var alloc: std.mem.Allocator = undefined;
|
||||
|
||||
var running: bool = false;
|
||||
var time: Time = .{ .delta = 0, .now = 0 };
|
||||
|
@@ -1,10 +1,11 @@
|
||||
const Graphics = @import("graphics.zig");
|
||||
const Entity = @import("entity.zig");
|
||||
const Time = @import("time.zig");
|
||||
const comp = @import("components.zig");
|
||||
|
||||
pub var time: Time = undefined;
|
||||
var next_stop: Time = undefined;
|
||||
var entities: [16]?Entity = undefined;
|
||||
var entities: comp.Storage(Entity, .{}) = undefined;
|
||||
|
||||
pub var plane_mesh: Graphics.Mesh = undefined;
|
||||
pub var cube_mesh: Graphics.Mesh = undefined;
|
||||
@@ -12,25 +13,25 @@ pub var texture: Graphics.Texture = undefined;
|
||||
|
||||
const World = @This();
|
||||
pub fn initDebug() void {
|
||||
entities = .{null} ** 16;
|
||||
entities[0] = .{
|
||||
entities = comp.Storage(Entity, .{}).init();
|
||||
_ = entities.add(.{
|
||||
.position = .{ 0, 0 },
|
||||
.player = true,
|
||||
};
|
||||
entities[1] = .{
|
||||
});
|
||||
_ = entities.add(.{
|
||||
.position = .{ 2, 0 },
|
||||
.enemy = true,
|
||||
.controller = .{
|
||||
.move_units = 0.25,
|
||||
},
|
||||
};
|
||||
entities[2] = .{
|
||||
});
|
||||
_ = entities.add(.{
|
||||
.position = .{ 3, 0 },
|
||||
.enemy = true,
|
||||
.controller = .{
|
||||
.move_units = 0.25,
|
||||
},
|
||||
};
|
||||
});
|
||||
time = Time.ZERO;
|
||||
World.plane_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
||||
World.cube_mesh = Graphics.loadMesh(@ptrCast(&CUBE_MESH_DATA));
|
||||
@@ -41,6 +42,7 @@ pub fn deinit() void {
|
||||
Graphics.unloadMesh(World.plane_mesh);
|
||||
Graphics.unloadMesh(World.cube_mesh);
|
||||
Graphics.unloadTexture(World.texture);
|
||||
World.entities.deinit();
|
||||
}
|
||||
|
||||
pub fn updateReal(delta: f32) void {
|
||||
@@ -49,16 +51,18 @@ pub fn updateReal(delta: f32) void {
|
||||
const current = Time.earliest(World.next_stop, update_until);
|
||||
defer World.time = current;
|
||||
|
||||
for (&World.entities) |*entity| {
|
||||
if (entity.*) |*e| e.update();
|
||||
var iter = World.entities.iter();
|
||||
while (iter.next()) |entity| {
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(delta: f32) void {
|
||||
Graphics.drawMesh(World.plane_mesh, World.texture, .{ .scale = @splat(5) });
|
||||
for (&World.entities) |*entity| {
|
||||
if (entity.*) |*e| e.draw(delta);
|
||||
var iter = World.entities.iter();
|
||||
while (iter.next()) |entity| {
|
||||
entity.draw(delta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,12 +71,11 @@ pub fn requestUpdate(at: Time) void {
|
||||
}
|
||||
|
||||
pub fn entityAt(position: @Vector(2, i32)) ?*Entity {
|
||||
for (&World.entities) |*maybe_entity| {
|
||||
if (maybe_entity.*) |*entity| {
|
||||
var iter = World.entities.iter();
|
||||
while (iter.next()) |entity| {
|
||||
if (@reduce(.And, entity.position == position))
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -81,12 +84,11 @@ pub fn isFree(position: @Vector(2, i32)) bool {
|
||||
}
|
||||
|
||||
pub fn getPlayer() ?*Entity {
|
||||
for (&World.entities) |*maybe_entity| {
|
||||
if (maybe_entity.*) |*entity| {
|
||||
var iter = World.entities.iter();
|
||||
while (iter.next()) |entity| {
|
||||
if (entity.player)
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user