just a bunch of cleanup to entities
parent
a6d543ced5
commit
2ebfdb8db0
|
|
@ -2,35 +2,77 @@ const assets = @import("assets.zig");
|
|||
const Layer = @import("Layer.zig");
|
||||
const Color = @import("Color.zig");
|
||||
const Recti = @import("geometry/Recti.zig");
|
||||
const std = @import("std");
|
||||
|
||||
const Entity = @This();
|
||||
|
||||
const EntityOptions = struct {
|
||||
renders: bool = true,
|
||||
updates: bool = true,
|
||||
accepts_keyboard: bool = false,
|
||||
accepts_mouse: bool = false,
|
||||
};
|
||||
|
||||
ptr: *const anyopaque,
|
||||
ptr: *anyopaque,
|
||||
options: EntityOptions,
|
||||
destroyFn: *const fn(*const anyopaque) void,
|
||||
updateFn: *const fn(*anyopaque, f32) void,
|
||||
drawFn: *const fn(*const anyopaque) void,
|
||||
|
||||
pub fn init(ptr: anytype, options: EntityOptions) Entity {
|
||||
const MutablePointer = @TypeOf(ptr);
|
||||
// @compileLog("Compiling Entity type for " ++ @typeName(MutablePointer));
|
||||
|
||||
pub fn init(ptr: anytype) Entity {
|
||||
const type_info = @typeInfo(@TypeOf(ptr));
|
||||
const type_info = @typeInfo(MutablePointer);
|
||||
|
||||
// ensure the passed type is a mutable pointer
|
||||
if(type_info != .Pointer) @compileError("Entity implementation must be a pointer");
|
||||
// to a single thing
|
||||
if(type_info.Pointer.size != .One) @compileError("Entity pointer must be a single item pointer");
|
||||
// where that thing is a struct or opaque
|
||||
switch (@typeInfo(type_info.Pointer.child)) {
|
||||
.Struct => {},
|
||||
else => @compileError("Entity pointer must point to a struct or opaque type"),
|
||||
}
|
||||
|
||||
// also take the const pointer type, as we will use both mutable an immutable pointers.
|
||||
// some entities mutate and some do not
|
||||
const ConstPointer = *const @typeInfo(MutablePointer).Pointer.child;
|
||||
// @compileLog("const pointer type: " ++ @typeName(ConstPointer));
|
||||
|
||||
const gen = struct {
|
||||
pub fn destroyImpl(pointer: *const anyopaque) void {
|
||||
const self: ConstPointer = @ptrCast(@alignCast(pointer));
|
||||
type_info.Pointer.child.destroy(self);
|
||||
}
|
||||
pub fn updateImpl(pointer: *anyopaque, dt: f32) void {
|
||||
const self: MutablePointer = @ptrCast(@alignCast(pointer));
|
||||
type_info.Pointer.child.update(self, dt);
|
||||
}
|
||||
pub fn drawImpl(pointer: *const anyopaque) void {
|
||||
const self: @TypeOf(ptr) = @ptrCast(@alignCast(pointer));
|
||||
const self: ConstPointer = @ptrCast(@alignCast(pointer));
|
||||
type_info.Pointer.child.draw(self);
|
||||
// @call(.{ .modifier = .always_inline }, ptr_info.Pointer.child.draw, .{ self });
|
||||
// draw(self);
|
||||
}
|
||||
};
|
||||
|
||||
return .{
|
||||
.ptr = ptr,
|
||||
.options = options,
|
||||
.destroyFn = gen.destroyImpl,
|
||||
|
||||
.updateFn = gen.updateImpl,
|
||||
.drawFn = gen.drawImpl,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn update(self: *const Entity, dt: f32) void {
|
||||
self.updateFn(self.ptr, dt);
|
||||
}
|
||||
|
||||
pub fn draw(self: *const Entity) void {
|
||||
self.drawFn(self.ptr);
|
||||
}
|
||||
|
||||
pub fn destroy(self: *const Entity) void {
|
||||
self.destroyFn(self.ptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
const Scene = @This();
|
||||
|
||||
const assets = @import("assets.zig");
|
||||
const Recti = @import("geometry/Recti.zig");
|
||||
const Layer = @import("Layer.zig");
|
||||
|
|
@ -7,13 +9,6 @@ const Terrain = @import("Terrain.zig");
|
|||
const std = @import("std");
|
||||
const ArrayList = std.ArrayList;
|
||||
|
||||
const Scene = @This();
|
||||
// const DrawFunction = fn() void;
|
||||
// const UpdateFunction = fn(f32) void;
|
||||
|
||||
// draw: DrawFunction,
|
||||
// update:
|
||||
|
||||
entities: ArrayList(Entity),
|
||||
|
||||
pub fn new() Scene {
|
||||
|
|
@ -24,14 +19,46 @@ pub fn new() Scene {
|
|||
}
|
||||
|
||||
pub fn destroy(self: *Scene) void {
|
||||
for (self.entities.items) |entity| {
|
||||
entity.destroy();
|
||||
}
|
||||
self.entities.deinit();
|
||||
}
|
||||
|
||||
pub fn start(self: *Scene) !void {
|
||||
const terrain = Terrain.new();
|
||||
// terrain.entity();
|
||||
const terrain = try Terrain.create();
|
||||
try self.add(terrain);
|
||||
}
|
||||
|
||||
try self.entities.append(terrain.entity());
|
||||
// ---
|
||||
|
||||
pub fn add(self: *Scene, instance_ptr: anytype) !void {
|
||||
const instance_ptr_type = @TypeOf(instance_ptr);
|
||||
const instance_ptr_type_info = @typeInfo(instance_ptr_type);
|
||||
|
||||
if (instance_ptr_type_info != .Pointer)
|
||||
@compileError(
|
||||
"Cannot add to scene type " ++
|
||||
@typeName(instance_ptr_type) ++
|
||||
"Must be a mutable pointer\n"
|
||||
);
|
||||
if (instance_ptr_type_info.Pointer.size != .One)
|
||||
@compileError("Pointer size must be One");
|
||||
if (instance_ptr_type_info.Pointer.is_const)
|
||||
@compileError("Pointer must be mutable");
|
||||
|
||||
const instance_type = instance_ptr_type_info.Pointer.child;
|
||||
|
||||
if (!@hasDecl(instance_type, "entity"))
|
||||
@compileError("Pointer must be to a struct with fn entity() Entity");
|
||||
|
||||
try self.entities.append(instance_ptr.entity());
|
||||
}
|
||||
|
||||
pub fn update(self: *Scene, dt: f32) void {
|
||||
for (self.entities.items) |entity| {
|
||||
entity.update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(self: *Scene) void {
|
||||
|
|
@ -45,4 +72,16 @@ pub fn draw(self: *Scene) void {
|
|||
assets.heart.draw(&Recti.from_xywh(80, 100, 32, 64), Layer.ENTITIES, Color.INDIGO);
|
||||
}
|
||||
|
||||
// --- helpfer functions for entities themselves
|
||||
|
||||
// an entity can choose to allocate itself however it pleases, but these
|
||||
// are good default functions that just throw things on the heap.
|
||||
pub fn allocate(instance: anytype) !*@TypeOf(instance) {
|
||||
const ptr = try std.heap.page_allocator.create(@TypeOf(instance));
|
||||
ptr.* = instance;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
pub fn deallocate(instance: anytype) void {
|
||||
std.heap.page_allocator.destroy(instance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,21 +5,41 @@ const Layer = @import("Layer.zig");
|
|||
const Color = @import("Color.zig");
|
||||
const Recti = @import("geometry/Recti.zig");
|
||||
const Entity = @import("Entity.zig");
|
||||
const Scene = @import("Scene.zig");
|
||||
const std = @import("std");
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
|
||||
size: u32 = 24,
|
||||
draw: u8 = 4,
|
||||
size: u16 = 24,
|
||||
|
||||
pub fn new() Terrain {
|
||||
return .{};
|
||||
pub fn entity(self: *Terrain) Entity {
|
||||
return Entity.init(self, .{});
|
||||
}
|
||||
|
||||
pub fn draw(_: *const Terrain) void {
|
||||
pub fn create() !*Terrain {
|
||||
return try Scene.allocate(Terrain {
|
||||
.size = 24,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn destroy(self: *const Terrain) void {
|
||||
Scene.deallocate(self);
|
||||
}
|
||||
|
||||
pub fn update(self: *Terrain, _: f32) void {
|
||||
if (prng.random().int(u8) == 34) {
|
||||
self.size = self.size + 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(self: *const Terrain) void {
|
||||
for(0..self.size) |y| {
|
||||
for(0..self.size) |x| {
|
||||
const idx: usize = @intFromFloat(@floor(prng.random().float(f32) * 4));
|
||||
assets.terrain[idx].draw(&Recti.from_xywh(200, 100, 64, 64), Layer.FLOOR, Color.WHITE);
|
||||
var grey = prng.random().float(f32);
|
||||
grey /= 4.0;
|
||||
grey += 3.0 / 4.0;
|
||||
const rect = Recti.from_xywh(@intCast(100 + 16 * x), @intCast(100 + 16 * y), 16, 16);
|
||||
assets.terrain[idx].draw(&rect, Layer.FLOOR, Color.rgba(grey, grey, grey, 1));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entity(self: *const Terrain) Entity {
|
||||
return Entity.init(self);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue