Files
voxel-game/src/main.zig

175 lines
5.3 KiB
Zig

const std = @import("std");
const glfw = @import("zglfw");
const stbi = @import("zstbi");
const vk = @import("vulkan");
const c = @import("const.zig");
const atoms = @import("engine/Atom.zig");
const Engine = @import("engine/Engine.zig");
const Swapchain = @import("engine/Swapchain.zig");
const Game = @import("Game.zig");
pub const std_options: std.Options = .{
.log_scope_levels = &.{
.{
.scope = .vulkan,
.level = .debug,
},
.{
.scope = .deinit,
// Change to `.debug` to see a log when calling `deinit`.
.level = .info,
},
},
};
pub fn main() !void {
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
try atoms.init(allocator);
defer atoms.deinit();
stbi.init(allocator);
defer stbi.deinit();
glfw.init() catch |err| {
std.log.err("Could not initialize GLFW", .{});
return err;
};
defer glfw.terminate();
if (!glfw.isVulkanSupported()) {
std.log.err("Vulkan is not supported by this system", .{});
return error.NoVulkan;
}
glfw.windowHint(.client_api, .no_api);
var window = glfw.Window.create(c.default_window_width, c.default_window_height, c.window_title, null) catch |err| {
std.log.err("Could not create window", .{});
return err;
};
defer window.destroy();
window.setSizeLimits(c.min_window_width, c.min_window_height, -1, -1);
window.setInputMode(.cursor, .disabled) catch {};
if (glfw.rawMouseMotionSupported()) {
window.setInputMode(.raw_mouse_motion, true) catch {};
}
_ = window.setKeyCallback(keyCallback);
_ = window.setCursorPosCallback(cursorPosCallback);
_ = window.setMouseButtonCallback(mouseButtonCallback);
var engine = try Engine.init(allocator, window);
defer engine.deinit();
var swapchain = try Swapchain.init(&engine);
defer swapchain.deinit(&engine);
var game = try Game.init(allocator, &engine, &swapchain);
var callback_context: CallbackContext = blk: {
const cursor_last_xpos, const cursor_last_ypos = window.getCursorPos();
break :blk .{
.game = &game,
.cursor_last_xpos = cursor_last_xpos,
.cursor_last_ypos = cursor_last_ypos,
.focused = (window.getInputMode(.cursor) catch .normal) == .disabled,
};
};
window.setUserPointer(&callback_context);
defer {
window.setUserPointer(null);
game.deinit();
}
var t1 = glfw.getTime();
while (!window.shouldClose()) {
glfw.pollEvents();
const t2 = glfw.getTime();
const dt: f32 = @floatCast(t2 - t1);
t1 = t2;
game.update(dt);
}
std.log.debug("Exitted the game loop", .{});
engine.waitForFence(swapchain.fence) catch {};
engine.deviceWaitIdle() catch {};
}
const CallbackContext = struct {
game: *Game,
focused: bool,
cursor_last_xpos: f64,
cursor_last_ypos: f64,
};
fn keyCallback(window: *glfw.Window, key_code: glfw.Key, _: c_int, action: glfw.Action, _: glfw.Mods) callconv(.c) void {
const maybe_ctx = window.getUserPointer(CallbackContext);
if (key_code == .escape and action == .press and (window.getInputMode(.cursor) catch .normal) == .disabled) {
window.setInputMode(.cursor, .normal) catch {};
if (maybe_ctx) |ctx| {
const cursor_last_xpos, const cursor_last_ypos = window.getCursorPos();
ctx.cursor_last_xpos = cursor_last_xpos;
ctx.cursor_last_ypos = cursor_last_ypos;
ctx.focused = false;
}
return;
}
if (maybe_ctx) |ctx| {
if (ctx.focused) {
switch (action) {
.press => ctx.game.onKeyDown(key_code),
.release => ctx.game.onKeyUp(key_code),
.repeat => {},
}
}
}
}
fn cursorPosCallback(window: *glfw.Window, cursor_xpos: f64, cursor_ypos: f64) callconv(.c) void {
const maybe_ctx = window.getUserPointer(CallbackContext);
if (maybe_ctx) |ctx| {
if (ctx.focused) {
const dx: f32 = @floatCast(cursor_xpos - ctx.cursor_last_xpos);
const dy: f32 = @floatCast(cursor_ypos - ctx.cursor_last_ypos);
ctx.game.onMouseMove(dx, dy);
ctx.cursor_last_xpos = cursor_xpos;
ctx.cursor_last_ypos = cursor_ypos;
}
}
}
fn mouseButtonCallback(window: *glfw.Window, button: glfw.MouseButton, action: glfw.Action, _: glfw.Mods) callconv(.c) void {
const maybe_ctx = window.getUserPointer(CallbackContext);
if (button == .left and action == .press and (window.getInputMode(.cursor) catch .normal) == .normal) {
window.setInputMode(.cursor, .disabled) catch {};
if (maybe_ctx) |ctx| {
const cursor_last_xpos, const cursor_last_ypos = window.getCursorPos();
ctx.cursor_last_xpos = cursor_last_xpos;
ctx.cursor_last_ypos = cursor_last_ypos;
ctx.focused = true;
}
}
if (maybe_ctx) |ctx| {
if (ctx.focused) {
switch (action) {
.press => ctx.game.onMouseDown(button),
.release => ctx.game.onMouseUp(button),
.repeat => {},
}
}
}
}