551 lines
17 KiB
Zig
551 lines
17 KiB
Zig
allocator: std.mem.Allocator,
|
|
moveInput: *core.Axis2dBinding = undefined,
|
|
|
|
cameraSpeed: f32 = 10.0,
|
|
moveVector: core.Vectorf = .{},
|
|
mouseMove: core.Vector2f = .{},
|
|
verticalMove: f32 = 0.0,
|
|
|
|
centerDist: f32 = 2.0,
|
|
centerDistMove: f32 = 2.0,
|
|
|
|
mouseLook: bool = true,
|
|
showWindow: bool = true,
|
|
|
|
fpcamera: *FpCamera = undefined,
|
|
|
|
// videoplayer: *VideoPlayer = undefined,
|
|
// videoplayerObject: core.Entity = undefined,
|
|
|
|
objectSpawner: *extras.ObjectSpawner = undefined,
|
|
|
|
inputEnabled: bool = true,
|
|
videoFullbright: bool = false,
|
|
|
|
//moveLight: bool = true,
|
|
|
|
tbMap: ?*bsp.maploader.TBMap = null,
|
|
|
|
// addFunc: ?*const fn (i32, i32) callconv(.C) i32 = undefined,
|
|
|
|
engineTool: *extras.EngineTool = undefined,
|
|
|
|
modules: std.AutoHashMapUnmanaged(u32, []const u8) = .{},
|
|
|
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "SampleGame");
|
|
|
|
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
|
const self = try allocator.create(@This());
|
|
self.* = .{
|
|
.allocator = allocator,
|
|
};
|
|
return self;
|
|
}
|
|
|
|
const assetReferences = [_]assets.AssetImportReference{
|
|
assets.MakeImportRefOptions(
|
|
"Mesh",
|
|
"m_skybox",
|
|
.{ .path = "meshes/skybox.obj" },
|
|
),
|
|
assets.MakeImportRefOptions(
|
|
"Mesh",
|
|
"m_fox",
|
|
.{ .path = "gltf-samples/Fox/glTF/Fox.gltf" },
|
|
),
|
|
assets.MakeImportRefOptions(
|
|
"Texture",
|
|
"t_fox",
|
|
.{ .path = "gltf-samples/Fox/glTF/Texture.png" },
|
|
),
|
|
assets.MakeImportRefOptions("Texture", "t_crate", .{
|
|
.path = "textures/Crate.png",
|
|
}),
|
|
assets.MakeImportRefOptions(
|
|
"Mesh",
|
|
"m_crate",
|
|
.{ .path = "meshes/crate.obj" },
|
|
),
|
|
assets.MakeImportRefOptions(
|
|
"Texture",
|
|
"t_skybox",
|
|
.{
|
|
.textureCube = true,
|
|
.textureList = &.{
|
|
"sky_air/cube_right.png", // cubemapfacePositivex, right
|
|
"sky_air/cube_left.png", // cubemapfacePositivex, right
|
|
"sky_air/cube_up.png", // cubemapfacePositivex, right
|
|
"sky_air/cube_down.png", // cubemapfacePositivex, right
|
|
"sky_air/cube_back.png", // cubemapfacePositivex, right
|
|
"sky_air/cube_front.png", // cubemapfacePositivex, right
|
|
},
|
|
},
|
|
),
|
|
};
|
|
|
|
pub const FoxObject = struct {
|
|
data: core.GameObjectData = undefined,
|
|
entity: core.Entity,
|
|
|
|
pub fn create(alloc: std.mem.Allocator) !*@This() {
|
|
const self = try alloc.create(@This());
|
|
const fox = try core.createEntity();
|
|
const scene = fox.addComponent(core.Scene).?;
|
|
|
|
scene.setScale(0.01, 0.01, 0.01);
|
|
const mesh = fox.addComponent(rend.MeshComponent).?;
|
|
mesh.setMesh("m_fox");
|
|
mesh.setTexture("t_fox");
|
|
|
|
self.entity = fox;
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn getEntity(self: *@This()) core.Entity {
|
|
return self.entity;
|
|
}
|
|
|
|
pub fn destroy(self: *@This()) void {
|
|
self.entity.destroy();
|
|
self.data.release(self);
|
|
}
|
|
};
|
|
|
|
pub const DamagedHelmet = struct {
|
|
data: core.GameObjectData = undefined,
|
|
entity: core.Entity,
|
|
|
|
var first: bool = true;
|
|
pub fn create(alloc: std.mem.Allocator) !*@This() {
|
|
const refs = [_]assets.AssetImportReference{ assets.MakeImportRefOptions(
|
|
"Mesh",
|
|
"m_damagedHelmet",
|
|
.{ .path = "gltf-samples/DamagedHelmet/glTF/DamagedHelmet.gltf" },
|
|
), assets.MakeImportRefOptions(
|
|
"Texture",
|
|
"t_damagedHelmet",
|
|
.{ .path = "gltf-samples/DamagedHelmet/glTF/Default_albedo.png" },
|
|
) };
|
|
|
|
if (first) {
|
|
first = false;
|
|
try assets.loadList(refs);
|
|
}
|
|
|
|
const self = try alloc.create(@This());
|
|
self.entity = try core.createEntity();
|
|
const scene = self.entity.addComponent(core.Scene).?;
|
|
_ = scene;
|
|
|
|
// scene.setScale(0.01, 0.01, 0.01);
|
|
const mesh = self.entity.addComponent(rend.MeshComponent).?;
|
|
mesh.setMesh("m_damagedHelmet");
|
|
mesh.setTexture("t_damagedHelmet");
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn getEntity(self: *@This()) core.Entity {
|
|
return self.entity;
|
|
}
|
|
|
|
pub fn destroy(self: *@This()) void {
|
|
self.entity.destroy();
|
|
self.data.release(self);
|
|
}
|
|
};
|
|
|
|
pub fn prepare(self: *@This()) !void {
|
|
core.engine_log(">>>>>>> game prepare", .{});
|
|
var z = core.tracy.ZoneN(@src(), "PREPARING GAME");
|
|
defer z.End();
|
|
try core.fs().addContentPath("sampleGame");
|
|
|
|
try core.loadModule("externGame", true);
|
|
|
|
self.engineTool = try extras.EngineTool.create(self.allocator);
|
|
|
|
// core.fs().watchPath("zig-out/modules");
|
|
// try core.fs().addFileChangedCallback(core.sharedLibName("externGame"), moduleChangedCallback, self);
|
|
|
|
// try self.tryLoadExtern("externGame");
|
|
|
|
// self.rendererDebugger = try extras.RendererDebug.create(self.allocator); //try core.createObject(extras.RendererDebug, .{});
|
|
_ = try core.createObject(extras.RendererDebug, .{});
|
|
|
|
//self.objectSpawner = try extras.ObjectSpawner.create(self.allocator);
|
|
self.objectSpawner = try core.createObject(extras.ObjectSpawner, .{});
|
|
try self.objectSpawner.addSpawnFunction("fox", FoxObject);
|
|
try self.objectSpawner.addSpawnFunction("doomplayer", DoomPlayer.DoomCanvas);
|
|
try self.objectSpawner.addSpawnFunction("empire", @import("empire.zig"));
|
|
try self.objectSpawner.addSpawnFunction("DamagedHelmet", DamagedHelmet);
|
|
|
|
try assets.loadList(assetReferences);
|
|
// self.videoplayer = try VideoPlayer.create(self.allocator);
|
|
// try self.videoplayer.startPlayback("LAPWING2.ogv");
|
|
// self.videoplayerObject = try self.videoplayer.createVideoPlayerEntity();
|
|
|
|
rend.setSkyboxTexture("t_skybox");
|
|
|
|
const exitInput = try core.ActionBinding.create(core.MakeName("exit"));
|
|
exitInput.addKey(.escape, .keyDown);
|
|
_ = exitInput.data.addListener(null, onExit);
|
|
exitInput.activate();
|
|
|
|
{
|
|
const inp = try core.ActionBinding.create(core.MakeName("slow"));
|
|
inp.addKey(.lshift, .keyDown);
|
|
inp.addKey(.lshift, .keyUp);
|
|
_ = inp.data.addListener(self, slowDown);
|
|
inp.activate();
|
|
}
|
|
|
|
self.fpcamera = try FpCamera.create(self.allocator);
|
|
self.fpcamera.setPosition(.{ .z = 15 });
|
|
self.fpcamera.activateCamera();
|
|
|
|
const moveInput = try core.Axis2dBinding.create(core.MakeName("movement"));
|
|
|
|
moveInput.addKey(.w, 1.0, .y);
|
|
moveInput.addKey(.s, -1.0, .y);
|
|
moveInput.addKey(.d, 1.0, .x);
|
|
moveInput.addKey(.a, -1.0, .x);
|
|
|
|
_ = moveInput.data.addListener(self, onMove);
|
|
moveInput.activate();
|
|
|
|
{
|
|
const i = try core.Axis1dBinding.create(core.MakeName("rotPitch"));
|
|
i.addKey(.f, 1.0);
|
|
i.addKey(.v, -1.0);
|
|
|
|
_ = i.data.addListener(self, distanceMove);
|
|
i.activate();
|
|
}
|
|
|
|
{
|
|
const verticalInput = try core.Axis1dBinding.create(core.MakeName("movementVertical"));
|
|
verticalInput.addKey(.e, 1.0);
|
|
verticalInput.addKey(.q, -1.0);
|
|
|
|
_ = verticalInput.data.addListener(self, verticalMovement);
|
|
verticalInput.activate();
|
|
}
|
|
|
|
{
|
|
const mouseLook = try core.Axis2dBinding.create(core.MakeName("mouseLook"));
|
|
mouseLook.enableMouseRelative();
|
|
_ = mouseLook.data.addListener(self, onMouseLook);
|
|
mouseLook.activate();
|
|
}
|
|
|
|
{
|
|
const shaderReload = try core.ActionBinding.create(core.MakeName("shaderReload"));
|
|
shaderReload.addKey(.r, .keyDown);
|
|
_ = shaderReload.data.addListener(self, onShaderReload);
|
|
shaderReload.activate();
|
|
}
|
|
|
|
{
|
|
const input = try core.ActionBinding.create(core.MakeName("toggleDoom"));
|
|
input.addKey(.f2, .keyDown);
|
|
_ = input.data.addListener(self, toggleDoom);
|
|
input.activate();
|
|
}
|
|
|
|
{
|
|
const input = try core.ActionBinding.create(core.MakeName("toggleMouseLook"));
|
|
input.addKey(.t, .keyDown);
|
|
_ = input.data.addListener(self, toggleMouseLook);
|
|
input.activate();
|
|
}
|
|
self.updateMouseLook();
|
|
}
|
|
|
|
fn onMouseLook(ctx: ?*anyopaque, axis: core.Vector2f) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
|
|
if (self.inputEnabled) {
|
|
self.fpcamera.addMouseMovement(axis);
|
|
}
|
|
}
|
|
|
|
fn toggleDoom(ctx: ?*anyopaque, action: core.ActionEvent) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
_ = action;
|
|
|
|
self.inputEnabled = !self.inputEnabled;
|
|
|
|
if (DoomPlayer.gDoom) |c| {
|
|
c.inputEnabled = !self.inputEnabled;
|
|
}
|
|
}
|
|
|
|
fn toggleMouseLook(ctx: ?*anyopaque, action: core.ActionEvent) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
_ = action;
|
|
|
|
self.mouseLook = !self.mouseLook;
|
|
if (!self.mouseLook)
|
|
self.showWindow = true;
|
|
|
|
self.updateMouseLook();
|
|
}
|
|
|
|
fn updateMouseLook(self: *@This()) void {
|
|
self.fpcamera.mouseLookEnabled = self.mouseLook;
|
|
platform.setMouseRelativeMode(self.mouseLook);
|
|
// platform.setImguiVisible(!self.mouseLook);
|
|
}
|
|
|
|
fn onShaderReload(ctx: ?*anyopaque, action: core.ActionEvent) void {
|
|
_ = ctx;
|
|
_ = action;
|
|
|
|
core.engine_log("reloading shaders, this is gonna cause some leaks but thats ok", .{});
|
|
rend.renderer.reloadShaders() catch unreachable;
|
|
}
|
|
|
|
fn slowDown(ctx: ?*anyopaque, action: core.ActionEvent) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
|
|
if (action == .keyUp) {
|
|
self.cameraSpeed = 10.0;
|
|
}
|
|
if (action == .keyDown) {
|
|
self.cameraSpeed = 4.0;
|
|
}
|
|
}
|
|
|
|
fn distanceMove(ctx: ?*anyopaque, axis: f32) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
self.centerDistMove = axis;
|
|
}
|
|
|
|
fn cameraRotate(ctx: ?*anyopaque, axis: f32) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
self.rotateAxis = axis;
|
|
}
|
|
|
|
fn verticalMovement(ctx: ?*anyopaque, axis: f32) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
self.verticalMove = axis;
|
|
}
|
|
|
|
fn onMove(ctx: ?*anyopaque, axis: core.Vector2f) void {
|
|
const self: *@This() = @ptrCast(@alignCast(ctx));
|
|
self.moveVector = .{ .x = axis.x, .z = axis.y, .y = 0.0 };
|
|
}
|
|
|
|
pub fn onExit(ctx: ?*anyopaque, action: core.ActionEvent) void {
|
|
_ = ctx;
|
|
_ = action;
|
|
|
|
core.exitNow();
|
|
}
|
|
|
|
pub fn getMouseMovement(self: *@This()) core.Vector2f {
|
|
const rv = self.mouseMove;
|
|
self.mouseMove = .{};
|
|
|
|
return rv;
|
|
}
|
|
|
|
pub fn tryLoadExtern(self: *@This(), gameName: []const u8) !void {
|
|
var buf = std.mem.zeroes([256]u8);
|
|
|
|
const os_tag = @import("builtin").os.tag;
|
|
|
|
var suffix: []const u8 = "dll";
|
|
var prefix: []const u8 = "";
|
|
if (os_tag == .linux) {
|
|
prefix = "lib";
|
|
suffix = "so";
|
|
} else if (os_tag == .macos) {
|
|
suffix = "dylib";
|
|
prefix = "lib";
|
|
}
|
|
|
|
const path = try std.fmt.bufPrint(&buf, "zig-out/modules/{s}{s}.{s}", .{ prefix, gameName, suffix });
|
|
var lib = try std.DynLib.open(path);
|
|
// std.debug.print("path: {s}", .{path});
|
|
|
|
self.addFunc = lib.lookup(@TypeOf(self.addFunc.?), "add");
|
|
}
|
|
|
|
pub fn tick(self: *@This(), dt: f64) void {
|
|
const fdt: f32 = @floatCast(dt);
|
|
|
|
// self.loadMap2() catch unreachable;
|
|
|
|
core.loopDelay(@src(), 1.0, dt, struct {
|
|
s: @TypeOf(self),
|
|
|
|
pub fn func(c: @This()) void {
|
|
_ = c;
|
|
// c.s.tryLoadExtern("externGame") catch unreachable;
|
|
}
|
|
}, .{ .s = self });
|
|
|
|
const z1 = tracy.ZoneN(@src(), "inputDebugger");
|
|
z1.End();
|
|
|
|
const z2 = tracy.ZoneN(@src(), "inputDebugger");
|
|
z2.End();
|
|
|
|
const z3 = tracy.ZoneN(@src(), "VideoPlayer");
|
|
//self.videoplayer.tick(dt);
|
|
z3.End();
|
|
|
|
const z4 = tracy.ZoneN(@src(), "fpCamera");
|
|
self.fpcamera.tick(dt);
|
|
z4.End();
|
|
|
|
const z5 = tracy.ZoneN(@src(), "");
|
|
DoomPlayer.maybeTick(dt);
|
|
z5.End();
|
|
|
|
var movement = self.fpcamera.getForwardXZ().fmul(self.moveVector.z * fdt * self.cameraSpeed);
|
|
movement = movement.add(self.fpcamera.getRightXZ().fmul(self.moveVector.x * fdt * self.cameraSpeed));
|
|
movement = movement.add(.{ .y = self.verticalMove * fdt * self.cameraSpeed });
|
|
self.centerDist += self.centerDistMove * fdt;
|
|
|
|
const pos = self.fpcamera.getPosition().add(movement);
|
|
|
|
if (self.inputEnabled) {
|
|
self.fpcamera.setPosition(pos);
|
|
}
|
|
|
|
self.fpcamera.resolve();
|
|
|
|
const forward = self.fpcamera.getForward();
|
|
const debugCenter = self.fpcamera.getPosition().add(forward.fmul(self.centerDist));
|
|
self.objectSpawner.spawnPosition = debugCenter;
|
|
self.objectSpawner.spawnRotation = core.Rotation.eulerY(core.radians(self.fpcamera.yaw));
|
|
|
|
//if (self.moveLight) {
|
|
// core.debugSphere(debugCenter, 0.3, .{});
|
|
// core.debugSphere(debugCenter, 0.1, .{ .color = .{ .x = 1.0 } });
|
|
// rend.context().lightPosition = debugCenter;
|
|
//}
|
|
|
|
// self.loadMap2() catch unreachable;
|
|
// show a window with the current camera's position
|
|
|
|
self.objectSpawner.windowOpen = !self.mouseLook;
|
|
if (!self.mouseLook) {
|
|
// self.engineTool.tick();
|
|
//if (ig.begin("meh", null, .{})) {
|
|
//if (ig.checkbox("move lights ", &self.moveLight)) {}
|
|
//}
|
|
//ig.end();
|
|
// self.objectSpawner.tick(dt);
|
|
// self.rendererDebugger.tick(dt);
|
|
// if (ig.begin("meh", null, .{})) {
|
|
// ig.textFmt("x:{d:.03} y:{d:.03} z:{d:.03}", .{ pos.x, pos.y, pos.z }) catch return;
|
|
// // if (ig.checkbox("video fullbright", &self.videoFullbright)) {
|
|
// // //if (self.videoplayerObject.fetch(rend.MeshComponent)) |mesh| {
|
|
// // // mesh.textureMode.fullbright = self.videoFullbright;
|
|
// // //}
|
|
// // }
|
|
|
|
// ig.textFmt("info: - WASD to move, mouse to look,\n- Q and E to go up and down", .{}) catch return;
|
|
// ig.textFmt("- shift to slow down camera speed", .{}) catch return;
|
|
// ig.textFmt("- T to enable/disable mouse cursor", .{}) catch return;
|
|
// ig.textFmt("- f2 to route all inputs to the doom player", .{}) catch return;
|
|
// ig.textFmt("- movingLight checkbox makes the light stop moving with you", .{}) catch return;
|
|
|
|
// //ig.textf("1 + 2 = {d}", .{self.addFunc.?(1, 2)});
|
|
|
|
// {
|
|
// ig.textf("modules dirty: ", .{});
|
|
// var i = self.modules.iterator();
|
|
// while (i.next()) |n| {
|
|
// ig.textf("{s} pending reload", .{n.value_ptr.*});
|
|
// }
|
|
// }
|
|
|
|
// if (ig.smallButton("reload map")) {
|
|
// self.loadMap2() catch unreachable;
|
|
// }
|
|
|
|
// if (ig.smallButton("destroy map")) {
|
|
// if (self.tbMap) |tbMap| {
|
|
// core.engine_log("killing the map", .{});
|
|
// tbMap.destroy();
|
|
// self.tbMap = null;
|
|
// }
|
|
// }
|
|
// }
|
|
// ig.end();
|
|
|
|
// if (ig.begin("mesh components", null, .{})) {
|
|
// for (rend.MeshComponent.BaseContainer.dense.items) |*v| {
|
|
// ig.textFmt("mesh: {s}", .{v.value.meshName.utf8()}) catch unreachable;
|
|
// }
|
|
// }
|
|
// ig.end();
|
|
|
|
// if (ig.begin("scene components", null, .{})) {
|
|
// for (core.Scene.BaseContainer.dense.items) |*v| {
|
|
// ig.textFmt("scene entity: {d}", .{v.value.handle.index}) catch unreachable;
|
|
// }
|
|
|
|
// ig.textf("window at 0x{x}", .{@intFromPtr(backlog.platform.context().window)});
|
|
// if (ig.smallButton("click to show sdl messagebox")) {
|
|
// // _ = backlog.platform.windowing.sdl3.c.SDL_ShowSimpleMessageBox(0, "lmao", "you lmaoed your last uwu", backlog.platform.context().window);
|
|
// }
|
|
// }
|
|
// ig.end();
|
|
}
|
|
}
|
|
|
|
pub fn deinit(self: *@This()) void {
|
|
self.modules.deinit(self.allocator);
|
|
// self.rendererDebugger.destroy();
|
|
DoomPlayer.DoomCanvas.cleanupDoom();
|
|
self.fpcamera.destroy();
|
|
|
|
// self.objectSpawner.destroy();
|
|
// self.videoplayer.destroy();
|
|
self.allocator.destroy(self);
|
|
}
|
|
|
|
pub fn main() anyerror!void {
|
|
var spec = try backlog.createSpecVariant(.{
|
|
.name = "sampleGame",
|
|
.imgui = true,
|
|
.physics = true,
|
|
.audio = true,
|
|
}, std.heap.c_allocator);
|
|
|
|
_ = backlog.initAndRun(&NeonObjectTable, &spec);
|
|
|
|
// try backlog.initializeAndRunStandardProgram(@This(), .{
|
|
// .name = "sampleGame",
|
|
// .enabledModules = .{
|
|
// .imgui = true,
|
|
// .physics = true,
|
|
// .audio = true,
|
|
// },
|
|
//});
|
|
}
|
|
|
|
const DoomPlayer = @import("doomplayer");
|
|
//const VideoPlayer = @import("videoplayer");
|
|
const extras = @import("gameExtras");
|
|
const bsp = @import("bsp");
|
|
|
|
const FpCamera = extras.FpCamera;
|
|
const std = @import("std");
|
|
const backlog = @import("Backlog");
|
|
const assets = backlog.assets;
|
|
const platform = backlog.platform;
|
|
const core = backlog.core;
|
|
const ig = backlog.imgui.api;
|
|
const rend = backlog.rend;
|
|
const script = core.script;
|
|
const tracy = core.tracy;
|
|
const ui = backlog.ui;
|