2024-08-23 17:22:01 -04:00
|
|
|
const Engine = @This();
|
|
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
const std = @import("std");
|
|
|
|
|
const Recti = @import("geometry/Recti.zig");
|
|
|
|
|
const Matrix4f = @import("geometry/Matrix4f.zig");
|
|
|
|
|
const shaders = @import("shaders.zig");
|
|
|
|
|
const Texture = @import("Texture.zig");
|
|
|
|
|
const Sprite = @import("Sprite.zig");
|
|
|
|
|
const Layer = @import("Layer.zig");
|
2024-08-21 16:36:46 -04:00
|
|
|
const Color = @import("Color.zig");
|
2024-08-21 17:40:04 -04:00
|
|
|
const Scene = @import("Scene.zig");
|
|
|
|
|
const assets = @import("assets.zig");
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
const c = @cImport({
|
|
|
|
|
@cInclude("glad/glad.h");
|
|
|
|
|
@cInclude("GLFW/glfw3.h");
|
|
|
|
|
});
|
2024-09-03 13:13:28 -04:00
|
|
|
const AutoHashMap = std.AutoHashMap;
|
2024-08-21 15:57:18 -04:00
|
|
|
|
2024-09-03 13:13:28 -04:00
|
|
|
var store: AutoHashMap(*c.GLFWwindow, *Engine) = AutoHashMap(*c.GLFWwindow, *Engine).init(std.heap.page_allocator);
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
// export const IGame = struct {
|
|
|
|
|
// render: fn () void,
|
|
|
|
|
// update: fn (f32) void,
|
|
|
|
|
// };
|
2024-08-23 17:22:01 -04:00
|
|
|
current_scene: Scene,
|
2024-09-03 13:13:28 -04:00
|
|
|
projection: Matrix4f = undefined,
|
2024-08-21 15:57:18 -04:00
|
|
|
|
2024-08-23 17:22:01 -04:00
|
|
|
pub fn create(initial_scene: Scene) Engine {
|
|
|
|
|
return .{
|
|
|
|
|
.current_scene = initial_scene
|
|
|
|
|
};
|
|
|
|
|
}
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
fn errorCallback(err: c_int, desc_c: [*c]const u8) callconv(.C) void {
|
|
|
|
|
const desc: *const u8 = @ptrCast(desc_c);
|
|
|
|
|
std.log.err("glfw error {x:0>8}: {s}", .{ err, desc });
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-03 13:13:28 -04:00
|
|
|
fn on_resize (window: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
|
|
|
|
|
std.debug.print("[Engine:on_resize] {?}: {d} x {d}\n", .{ window, width, height });
|
|
|
|
|
c.glViewport(0, 0, width, height);
|
|
|
|
|
const engine_instance = store.get(window.?).?;
|
|
|
|
|
engine_instance.set_matrices(width, height);
|
|
|
|
|
engine_instance.current_scene.resize(width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_matrices(self: *Engine, width: i32, height: i32) void {
|
|
|
|
|
self.projection = Matrix4f.orthographic(0, @floatFromInt(width), @floatFromInt(height), 0, 0, 100);
|
|
|
|
|
shaders.set_projection_matrix(&self.projection);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
// export fn run(game: *const IGame) !void {
|
2024-08-23 17:22:01 -04:00
|
|
|
pub fn run(self: *Engine) !void {
|
2024-09-03 13:13:28 -04:00
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
// in case of errors, set callback early!
|
|
|
|
|
// for some reason this returns an error function as well??
|
|
|
|
|
_ = c.glfwSetErrorCallback(errorCallback);
|
|
|
|
|
|
|
|
|
|
// initialize glfw capabilities & cleanup
|
|
|
|
|
if (c.glfwInit() != 1) {
|
|
|
|
|
std.log.err("Failed to init glfw", .{});
|
|
|
|
|
return error.Initialization;
|
|
|
|
|
}
|
|
|
|
|
defer c.glfwTerminate();
|
|
|
|
|
|
|
|
|
|
// ensure glfw knows what we're about
|
|
|
|
|
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
|
c.glfwDefaultWindowHints();
|
|
|
|
|
c.glfwWindowHint(c.GLFW_SAMPLES, 4);
|
|
|
|
|
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 3);
|
|
|
|
|
// c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE);
|
|
|
|
|
|
|
|
|
|
// create the window & cleanup
|
|
|
|
|
const window = c.glfwCreateWindow(640, 480, "My Title", null, null) orelse {
|
|
|
|
|
std.log.err("Failed to open window", .{});
|
|
|
|
|
return error.Initialization;
|
|
|
|
|
};
|
|
|
|
|
defer c.glfwDestroyWindow(window);
|
|
|
|
|
|
2024-09-03 13:13:28 -04:00
|
|
|
try store.put(window, self);
|
|
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
// load opengl into the window
|
|
|
|
|
c.glfwMakeContextCurrent(window);
|
|
|
|
|
if (c.gladLoadGL() != 1) {
|
|
|
|
|
std.log.err("Failed to load GL context", .{});
|
|
|
|
|
return error.Initialization;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// configure the context!
|
|
|
|
|
c.glfwSwapInterval(1);
|
|
|
|
|
|
|
|
|
|
// compile shaders...
|
|
|
|
|
try shaders.load();
|
|
|
|
|
|
2024-08-21 17:40:04 -04:00
|
|
|
try assets.load();
|
|
|
|
|
|
2024-09-03 13:13:28 -04:00
|
|
|
_ = c.glfwSetWindowSizeCallback(window, on_resize);
|
|
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
const clearBrightness: f32 = 0.09;
|
|
|
|
|
c.glClearColor(clearBrightness, clearBrightness, clearBrightness, 1.0);
|
|
|
|
|
// c.glEnable(c.GL_MULTISAMPLE);
|
|
|
|
|
c.glDisable(c.GL_MULTISAMPLE);
|
2024-08-21 16:36:46 -04:00
|
|
|
c.glEnable(c.GL_BLEND);
|
|
|
|
|
c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
c.glEnable(c.GL_DEPTH_TEST);
|
|
|
|
|
c.glDepthFunc(c.GL_LEQUAL);
|
|
|
|
|
c.glDepthMask(c.GL_TRUE);
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
var width: c_int = undefined;
|
|
|
|
|
var height: c_int = undefined;
|
|
|
|
|
c.glfwGetFramebufferSize(window, @ptrCast(&width), @ptrCast(&height));
|
2024-09-03 13:13:28 -04:00
|
|
|
std.debug.print("[Engine:run] window size {d} x {d}\n", .{ width, height });
|
|
|
|
|
self.set_matrices(width, height);
|
|
|
|
|
try self.current_scene.start();
|
2024-08-21 15:57:18 -04:00
|
|
|
|
|
|
|
|
// run the main loop
|
|
|
|
|
while (c.glfwWindowShouldClose(window) == 0) {
|
|
|
|
|
c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT);
|
2024-08-23 17:22:01 -04:00
|
|
|
self.current_scene.draw();
|
2024-09-03 13:13:28 -04:00
|
|
|
assets.terrain[0][0].draw(Recti.from_xywh(-1000, -1000, 50000, 50000), Layer.FLOOR, Color.WHITE);
|
2024-08-21 17:40:04 -04:00
|
|
|
|
2024-08-21 15:57:18 -04:00
|
|
|
c.glfwSwapBuffers(window);
|
|
|
|
|
c.glfwPollEvents();
|
2024-08-23 17:22:01 -04:00
|
|
|
|
|
|
|
|
self.current_scene.update(0.0042);
|
2024-08-21 15:57:18 -04:00
|
|
|
}
|
|
|
|
|
}
|