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,
|
now: sdl.Time,
|
||||||
};
|
};
|
||||||
|
|
||||||
var alloc: std.mem.Allocator = undefined;
|
pub var alloc: std.mem.Allocator = undefined;
|
||||||
|
|
||||||
var running: bool = false;
|
var running: bool = false;
|
||||||
var time: Time = .{ .delta = 0, .now = 0 };
|
var time: Time = .{ .delta = 0, .now = 0 };
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
const Graphics = @import("graphics.zig");
|
const Graphics = @import("graphics.zig");
|
||||||
const Entity = @import("entity.zig");
|
const Entity = @import("entity.zig");
|
||||||
const Time = @import("time.zig");
|
const Time = @import("time.zig");
|
||||||
|
const comp = @import("components.zig");
|
||||||
|
|
||||||
pub var time: Time = undefined;
|
pub var time: Time = undefined;
|
||||||
var next_stop: 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 plane_mesh: Graphics.Mesh = undefined;
|
||||||
pub var cube_mesh: Graphics.Mesh = undefined;
|
pub var cube_mesh: Graphics.Mesh = undefined;
|
||||||
@@ -12,25 +13,25 @@ pub var texture: Graphics.Texture = undefined;
|
|||||||
|
|
||||||
const World = @This();
|
const World = @This();
|
||||||
pub fn initDebug() void {
|
pub fn initDebug() void {
|
||||||
entities = .{null} ** 16;
|
entities = comp.Storage(Entity, .{}).init();
|
||||||
entities[0] = .{
|
_ = entities.add(.{
|
||||||
.position = .{ 0, 0 },
|
.position = .{ 0, 0 },
|
||||||
.player = true,
|
.player = true,
|
||||||
};
|
});
|
||||||
entities[1] = .{
|
_ = entities.add(.{
|
||||||
.position = .{ 2, 0 },
|
.position = .{ 2, 0 },
|
||||||
.enemy = true,
|
.enemy = true,
|
||||||
.controller = .{
|
.controller = .{
|
||||||
.move_units = 0.25,
|
.move_units = 0.25,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
entities[2] = .{
|
_ = entities.add(.{
|
||||||
.position = .{ 3, 0 },
|
.position = .{ 3, 0 },
|
||||||
.enemy = true,
|
.enemy = true,
|
||||||
.controller = .{
|
.controller = .{
|
||||||
.move_units = 0.25,
|
.move_units = 0.25,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
time = Time.ZERO;
|
time = Time.ZERO;
|
||||||
World.plane_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
World.plane_mesh = Graphics.loadMesh(@ptrCast(&PLANE_MESH_DATA));
|
||||||
World.cube_mesh = Graphics.loadMesh(@ptrCast(&CUBE_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.plane_mesh);
|
||||||
Graphics.unloadMesh(World.cube_mesh);
|
Graphics.unloadMesh(World.cube_mesh);
|
||||||
Graphics.unloadTexture(World.texture);
|
Graphics.unloadTexture(World.texture);
|
||||||
|
World.entities.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateReal(delta: f32) void {
|
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);
|
const current = Time.earliest(World.next_stop, update_until);
|
||||||
defer World.time = current;
|
defer World.time = current;
|
||||||
|
|
||||||
for (&World.entities) |*entity| {
|
var iter = World.entities.iter();
|
||||||
if (entity.*) |*e| e.update();
|
while (iter.next()) |entity| {
|
||||||
|
entity.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(delta: f32) void {
|
pub fn draw(delta: f32) void {
|
||||||
Graphics.drawMesh(World.plane_mesh, World.texture, .{ .scale = @splat(5) });
|
Graphics.drawMesh(World.plane_mesh, World.texture, .{ .scale = @splat(5) });
|
||||||
for (&World.entities) |*entity| {
|
var iter = World.entities.iter();
|
||||||
if (entity.*) |*e| e.draw(delta);
|
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 {
|
pub fn entityAt(position: @Vector(2, i32)) ?*Entity {
|
||||||
for (&World.entities) |*maybe_entity| {
|
var iter = World.entities.iter();
|
||||||
if (maybe_entity.*) |*entity| {
|
while (iter.next()) |entity| {
|
||||||
if (@reduce(.And, entity.position == position))
|
if (@reduce(.And, entity.position == position))
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +84,11 @@ pub fn isFree(position: @Vector(2, i32)) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPlayer() ?*Entity {
|
pub fn getPlayer() ?*Entity {
|
||||||
for (&World.entities) |*maybe_entity| {
|
var iter = World.entities.iter();
|
||||||
if (maybe_entity.*) |*entity| {
|
while (iter.next()) |entity| {
|
||||||
if (entity.player)
|
if (entity.player)
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user