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 Layer = @import("Layer.zig");
|
||||||
const Color = @import("Color.zig");
|
const Color = @import("Color.zig");
|
||||||
const Recti = @import("geometry/Recti.zig");
|
const Recti = @import("geometry/Recti.zig");
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const Entity = @This();
|
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,
|
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(MutablePointer);
|
||||||
const type_info = @typeInfo(@TypeOf(ptr));
|
|
||||||
|
|
||||||
|
// ensure the passed type is a mutable pointer
|
||||||
if(type_info != .Pointer) @compileError("Entity implementation must be a 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");
|
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 {
|
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 {
|
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);
|
type_info.Pointer.child.draw(self);
|
||||||
// @call(.{ .modifier = .always_inline }, ptr_info.Pointer.child.draw, .{ self });
|
|
||||||
// draw(self);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.ptr = ptr,
|
.ptr = ptr,
|
||||||
|
.options = options,
|
||||||
|
.destroyFn = gen.destroyImpl,
|
||||||
|
|
||||||
|
.updateFn = gen.updateImpl,
|
||||||
.drawFn = gen.drawImpl,
|
.drawFn = gen.drawImpl,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update(self: *const Entity, dt: f32) void {
|
||||||
|
self.updateFn(self.ptr, dt);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw(self: *const Entity) void {
|
pub fn draw(self: *const Entity) void {
|
||||||
self.drawFn(self.ptr);
|
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 assets = @import("assets.zig");
|
||||||
const Recti = @import("geometry/Recti.zig");
|
const Recti = @import("geometry/Recti.zig");
|
||||||
const Layer = @import("Layer.zig");
|
const Layer = @import("Layer.zig");
|
||||||
|
|
@ -7,13 +9,6 @@ const Terrain = @import("Terrain.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
|
|
||||||
const Scene = @This();
|
|
||||||
// const DrawFunction = fn() void;
|
|
||||||
// const UpdateFunction = fn(f32) void;
|
|
||||||
|
|
||||||
// draw: DrawFunction,
|
|
||||||
// update:
|
|
||||||
|
|
||||||
entities: ArrayList(Entity),
|
entities: ArrayList(Entity),
|
||||||
|
|
||||||
pub fn new() Scene {
|
pub fn new() Scene {
|
||||||
|
|
@ -24,14 +19,46 @@ pub fn new() Scene {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Scene) void {
|
pub fn destroy(self: *Scene) void {
|
||||||
|
for (self.entities.items) |entity| {
|
||||||
|
entity.destroy();
|
||||||
|
}
|
||||||
self.entities.deinit();
|
self.entities.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(self: *Scene) !void {
|
pub fn start(self: *Scene) !void {
|
||||||
const terrain = Terrain.new();
|
const terrain = try Terrain.create();
|
||||||
// terrain.entity();
|
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 {
|
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);
|
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 Color = @import("Color.zig");
|
||||||
const Recti = @import("geometry/Recti.zig");
|
const Recti = @import("geometry/Recti.zig");
|
||||||
const Entity = @import("Entity.zig");
|
const Entity = @import("Entity.zig");
|
||||||
|
const Scene = @import("Scene.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
var prng = std.rand.DefaultPrng.init(0);
|
var prng = std.rand.DefaultPrng.init(0);
|
||||||
|
|
||||||
size: u32 = 24,
|
size: u16 = 24,
|
||||||
draw: u8 = 4,
|
|
||||||
|
|
||||||
pub fn new() Terrain {
|
pub fn entity(self: *Terrain) Entity {
|
||||||
return .{};
|
return Entity.init(self, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(_: *const Terrain) void {
|
pub fn create() !*Terrain {
|
||||||
const idx: usize = @intFromFloat(@floor(prng.random().float(f32) * 4));
|
return try Scene.allocate(Terrain {
|
||||||
assets.terrain[idx].draw(&Recti.from_xywh(200, 100, 64, 64), Layer.FLOOR, Color.WHITE);
|
.size = 24,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entity(self: *const Terrain) Entity {
|
pub fn destroy(self: *const Terrain) void {
|
||||||
return Entity.init(self);
|
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));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue