Refactored OpaquePtr/Scene slightly.

Removed unused allegro.path.
This commit is contained in:
Sander Schobers 2024-05-02 18:39:59 +02:00
parent 93d9fe6c12
commit 5e2ac5f3fe
7 changed files with 106 additions and 63 deletions

View File

View File

@ -65,6 +65,13 @@ pub const Context = struct {
}; };
} }
pub fn enterScene(self: *Context, scene: Scene) void {
self.exitScene();
self.scene = scene;
scene.enter(self);
}
fn exitScene(self: *Context) void { fn exitScene(self: *Context) void {
if (self.scene) |scene| { if (self.scene) |scene| {
scene.exit(self); scene.exit(self);
@ -83,11 +90,8 @@ pub const Context = struct {
self.shouldQuit = true; self.shouldQuit = true;
} }
pub fn switchToScene(self: *Context, comptime SceneType: type, build: ?*const fn (*SceneType) void) !void { pub fn switchToScene(self: *Context, comptime SceneType: type) !void {
self.exitScene(); const scene = try Scene.init(SceneType, self.allocator);
self.enterScene(scene);
const scene = try Scene.init(SceneType, self.allocator, build);
self.scene = scene;
scene.enter(self);
} }
}; };

View File

@ -3,7 +3,7 @@ const Allocator = std.mem.Allocator;
pub const OpaquePtr = struct { pub const OpaquePtr = struct {
allocator: Allocator, allocator: Allocator,
object: usize = undefined, ptr: usize = undefined,
virtualTable: VirtualTable = undefined, virtualTable: VirtualTable = undefined,
const VirtualTable = struct { const VirtualTable = struct {
@ -13,28 +13,37 @@ pub const OpaquePtr = struct {
pub fn Object(comptime Type: type) type { pub fn Object(comptime Type: type) type {
return struct { return struct {
ptr: *Type, ptr: *Type,
opaquePtr: OpaquePtr, opaque_ptr: OpaquePtr,
}; };
} }
pub fn create(comptime Type: type, allocator: Allocator) !Object(Type) { pub fn create(comptime Type: type, allocator: Allocator) !OpaquePtr {
const ptr = try allocator.create(Type); const ptr = try allocator.create(Type);
const opaq = OpaquePtr{ return OpaquePtr.init(Type, allocator, ptr);
}
pub fn createObject(comptime Type: type, allocator: Allocator) !Object(Type) {
const ptr = try allocator.create(Type);
const opaq = OpaquePtr.init(Type, allocator, ptr);
return Object(Type){
.ptr = ptr,
.opaque_ptr = opaq,
};
}
fn init(comptime Type: type, allocator: Allocator, ptr: *Type) OpaquePtr {
return OpaquePtr{
.allocator = allocator, .allocator = allocator,
.object = @intFromPtr(ptr), .ptr = @intFromPtr(ptr),
.virtualTable = .{ .virtualTable = .{
.destroy = struct { .destroy = struct {
fn destroy(self: OpaquePtr) void { fn destroy(self: OpaquePtr) void {
const object = @as(*Type, @ptrFromInt(self.object)); const p = @as(*Type, @ptrFromInt(self.ptr));
self.allocator.destroy(object); self.allocator.destroy(p);
} }
}.destroy, }.destroy,
}, },
}; };
return Object(Type){
.ptr = ptr,
.opaquePtr = opaq,
};
} }
pub fn destroy(self: OpaquePtr) void { pub fn destroy(self: OpaquePtr) void {

View File

@ -5,9 +5,9 @@ pub fn Scene(comptime Context: type, comptime Event: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
object: usize = undefined, scene_ptr: usize = undefined,
virtualTable: VirtualTable = undefined, virtualTable: VirtualTable = undefined,
opaquePtr: ?OpaquePtr = null, opaque_ptr: ?OpaquePtr = null,
const VirtualTable = struct { const VirtualTable = struct {
enter: *const fn (Self, *Context) void, enter: *const fn (Self, *Context) void,
@ -37,52 +37,81 @@ pub fn Scene(comptime Context: type, comptime Event: type) type {
self.virtualTable.tick(self, ctx, t, dt); self.virtualTable.tick(self, ctx, t, dt);
} }
pub fn makeOpaque(comptime SceneType: type, object: *SceneType) Self { pub fn Builder(comptime SceneType: type) type {
return Self{ .object = @intFromPtr(object), .virtualTable = .{ return struct {
.enter = struct { const SelfBuilder = @This();
fn enter(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); pub const Object = struct {
scene.enter(ctx); ptr: *SceneType,
} opaque_ptr: Scene,
}.enter, };
.exit = struct {
fn exit(self: Self, ctx: *Context) void { pub fn init(allocator: std.mem.Allocator) !Self {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const ptr = try OpaquePtr.create(SceneType, allocator);
scene.exit(ctx); return SelfBuilder.initOpaque(ptr);
} }
}.exit,
.handle = struct { pub fn initBuild(allocator: std.mem.Allocator, build: *const fn (*SceneType) void) !Self {
fn handle(self: Self, ctx: *Context, event: Event) !void { const ptr = try OpaquePtr.createObject(SceneType, allocator);
const scene = @as(*SceneType, @ptrFromInt(self.object)); build(ptr.ptr);
try scene.handle(ctx, event); return SelfBuilder.initOpaque(ptr.opaque_ptr);
} }
}.handle,
.tick = struct { pub fn initObject(allocator: std.mem.Allocator) !Object {
fn tick(self: Self, ctx: *Context, t: f32, dt: f32) void { const ptr = try OpaquePtr.createObject(SceneType, allocator);
const scene = @as(*SceneType, @ptrFromInt(self.object)); return Object{
scene.tick(ctx, t, dt); .ptr = ptr.ptr,
} .opaque_ptr = SelfBuilder.initOpaque(ptr.opaque_ptr),
}.tick, };
.render = struct { }
fn render(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); pub fn initOpaque(ptr: OpaquePtr) Self {
scene.render(ctx); return Self{
} .scene_ptr = ptr.ptr,
}.render, .virtualTable = .{
} }; .enter = struct {
fn enter(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.enter(ctx);
}
}.enter,
.exit = struct {
fn exit(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.exit(ctx);
}
}.exit,
.handle = struct {
fn handle(self: Self, ctx: *Context, event: Event) !void {
const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
try scene.handle(ctx, event);
}
}.handle,
.tick = struct {
fn tick(self: Self, ctx: *Context, t: f32, dt: f32) void {
const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.tick(ctx, t, dt);
}
}.tick,
.render = struct {
fn render(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.render(ctx);
}
}.render,
},
.opaque_ptr = ptr,
};
}
};
} }
pub fn init(comptime SceneType: type, allocator: std.mem.Allocator, build: ?*const fn (*SceneType) void) !Self { pub fn init(comptime SceneType: type, allocator: std.mem.Allocator) !Self {
const object = try OpaquePtr.create(SceneType, allocator); return Builder(SceneType).init(allocator);
const scene = Self.makeOpaque(SceneType, object.ptr);
if (build) |b| {
b(object.ptr);
}
return scene;
} }
pub fn deinit(self: Self) void { pub fn deinit(self: Self) void {
if (self.opaquePtr) |ptr| { if (self.opaque_ptr) |ptr| {
ptr.destroy(); ptr.destroy();
} }
} }

View File

@ -7,6 +7,7 @@ const Context = @import("context.zig").Context;
const GameScene = @import("game_scene.zig").GameScene; const GameScene = @import("game_scene.zig").GameScene;
const Palette = @import("palette.zig").Palette; const Palette = @import("palette.zig").Palette;
const Renderer = @import("renderer.zig").Renderer; const Renderer = @import("renderer.zig").Renderer;
const Scene = @import("scene.zig").Scene;
const TitleScene = @import("title_scene.zig").TitleScene; const TitleScene = @import("title_scene.zig").TitleScene;
fn hexColor(hex: []const u8) allegro.Color { fn hexColor(hex: []const u8) allegro.Color {
@ -63,7 +64,7 @@ pub fn main() !void {
try renderer.registerFonts(); try renderer.registerFonts();
try context.switchToScene(TitleScene, null); context.switchToScene(TitleScene) catch unreachable;
var t = allegro.getTime(); var t = allegro.getTime();
const fpsBuffer = [_]u8{0} ** 32; const fpsBuffer = [_]u8{0} ** 32;

View File

@ -18,7 +18,7 @@ pub const MainMenuScene = struct {
switch (event.type) { switch (event.type) {
allegro.c.ALLEGRO_EVENT_KEY_CHAR => { allegro.c.ALLEGRO_EVENT_KEY_CHAR => {
switch (event.keyboard.keycode) { switch (event.keyboard.keycode) {
allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(GameScene, null), allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(GameScene),
else => {}, else => {},
} }
}, },

View File

@ -19,7 +19,7 @@ pub const TitleScene = struct {
switch (event.type) { switch (event.type) {
allegro.c.ALLEGRO_EVENT_KEY_CHAR => { allegro.c.ALLEGRO_EVENT_KEY_CHAR => {
switch (event.keyboard.keycode) { switch (event.keyboard.keycode) {
allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(MainMenuScene, null), allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(MainMenuScene),
else => {}, else => {},
} }
}, },