sokoban-v1/src/game.zig

149 lines
3.8 KiB
Zig

const std = @import("std");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const Engine = @import("engine_lib");
const FontId = Engine.Font.Id;
const Vec2 = Engine.Math.Vec2;
const rgb = Engine.Math.rgb;
const Game = @This();
const FontName = enum {
regular,
bold,
italic,
};
const AssetId = enum {
font_regular,
font_bold,
font_italic,
sound_wood,
texture_icon,
};
const State = struct {
gpa: Allocator,
player: Vec2,
};
pub fn init(opts: *const Engine.Init) callconv(.c) *anyopaque {
const gpa = opts.gpa;
const state = gpa.create(State) catch @panic("OOM");
state.* = State{
.gpa = gpa,
.player = .init(50, 50),
};
return state;
}
fn getFont(assets: Engine.Asset.Registry, font_name: FontName) FontId {
const asset_id = switch (font_name) {
.regular => AssetId.font_regular,
.bold => AssetId.font_bold,
.italic => AssetId.font_italic,
};
return assets.getFont(@intFromEnum(asset_id));
}
pub fn loadAssets(assets: *Engine.Asset.Loader) callconv(.c) void {
assets.addFont(@intFromEnum(AssetId.font_regular), "roboto-font/Roboto-Regular.ttf");
assets.addFont(@intFromEnum(AssetId.font_bold), "roboto-font/Roboto-Bold.ttf");
assets.addFont(@intFromEnum(AssetId.font_italic), "roboto-font/Roboto-Italic.ttf");
assets.addSound(@intFromEnum(AssetId.sound_wood), "wood01.ogg");
assets.addTexture(@intFromEnum(AssetId.texture_icon), "icon.png");
}
pub fn deinit(state_ptr: *anyopaque) callconv(.c) void {
const state: *State = @alignCast(@ptrCast(state_ptr));
const gpa = state.gpa;
gpa.destroy(state);
}
pub fn tick(state_ptr: *anyopaque, frame: *Engine.Frame) callconv(.c) void {
const state: *State = @alignCast(@ptrCast(state_ptr));
const dt = frame.deltaTime();
const canvas_size = Vec2.init(100, 100);
frame.canvas_size = canvas_size;
var dir = Vec2.init(0, 0);
if (frame.isKeyDown(.W)) {
dir.y -= 1;
}
if (frame.isKeyDown(.S)) {
dir.y += 1;
}
if (frame.isKeyDown(.A)) {
dir.x -= 1;
}
if (frame.isKeyDown(.D)) {
dir.x += 1;
}
dir = dir.normalized();
if (dir.x != 0 or dir.y != 0) {
frame.playAudio(.{
.id = frame.assets.getSound(@intFromEnum(AssetId.sound_wood)),
.volume = 0.1
});
}
state.player = state.player.add(dir.multiplyScalar(50 * dt));
frame.drawRectangle(.{
.rect = .{ .pos = .init(0, 0), .size = canvas_size },
.color = rgb(20, 20, 20)
});
const icon = frame.assets.getTexture(@intFromEnum(AssetId.texture_icon));
const size = Vec2.init(20, 20);
frame.drawRectangle(.{
.rect = .{
.pos = state.player.sub(size.divideScalar(2)),
.size = size
},
.color = rgb(200, 2, 200),
.sprite = .{
.texture = icon,
.uv = .unit
}
});
if (dir.x != 0 or dir.y != 0) {
frame.drawRectanglOutline(state.player.sub(size.divideScalar(2)), size, rgb(20, 20, 20), 3);
}
if (frame.mouse_position) |mouse_position| {
const mouse_size = Vec2.init(10, 10);
frame.drawRectangle(.{
.rect = .{
.pos = mouse_position.sub(mouse_size.divideScalar(2)),
.size = mouse_size
},
.color = rgb(20, 2, 200)
});
}
frame.drawText(state.player, "Player", .{
.font = getFont(frame.assets, .regular),
.size = 10
});
}
pub fn debug(state_ptr: *anyopaque, imgui: *Engine.ImGui) callconv(.c) void {
const state: *State = @alignCast(@ptrCast(state_ptr));
_ = state; // autofix
imgui.text("Hello World!\n", .{});
}
comptime {
Engine.exportCallbacksIfNeeded(init, tick, deinit, debug, loadAssets);
}