Backlog/projects/sampleGame/main.zig

522 lines
16 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(
"Skeleton",
"sk_fox",
.{ .path = "gltf-samples/Fox/glTF/skeleton.ozz" },
),
assets.MakeImportRefOptions(
"Animation",
"a_fox_survey",
.{ .path = "gltf-samples/Fox/glTF/Survey.ozz" },
),
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_dark_skybox",
.{
.textureCube = true,
.textureList = &.{
"textures/DarkGrey.png", // cubemapfacePositivex, right
"textures/DarkGrey.png", // cubemapfacePositivex, right
"textures/DarkGrey.png", // cubemapfacePositivex, right
"textures/DarkGrey.png", // cubemapfacePositivex, right
"textures/DarkGrey.png", // cubemapfacePositivex, right
"textures/DarkGrey.png", // cubemapfacePositivex, right
//"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
},
},
),
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 ParticleObject = struct {
data: core.GameObjectData = undefined,
entity: core.Entity,
pub fn create(alloc: std.mem.Allocator) !*@This() {
const self = try alloc.create(@This());
const e = try core.createEntity();
const particle = e.addComponent(rend.ParticleEmitter).?;
particle._showDebug = true;
particle.start();
particle.gravity = .{ .y = -9.8 };
self.entity = e;
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 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");
const animator = fox.addComponent(rend.Animator).?;
animator.setSkeleton("sk_fox");
animator.setAnimation("a_fox_survey");
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);
try backlog.loadDynamicModules();
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, .{});
const rendererDebug = try core.createObject(extras.RendererDebug, .{});
try rendererDebug.skyboxes.append(rendererDebug.allocator, core.MakeName("t_skybox"));
try rendererDebug.skyboxes.append(rendererDebug.allocator, core.MakeName("t_dark_skybox"));
//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("particle", ParticleObject);
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 {
core.engine_log("unable to reload shaders", .{});
};
}
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);
const z4 = tracy.ZoneN(@src(), "fpCamera");
self.fpcamera.tick(dt);
z4.End();
const z5 = tracy.ZoneN(@src(), "doomplayer");
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));
self.objectSpawner.windowOpen = !self.mouseLook;
}
pub fn deinit(self: *@This()) void {
self.modules.deinit(self.allocator);
// self.rendererDebugger.destroy();
DoomPlayer.DoomCanvas.cleanupDoom();
self.fpcamera.destroy();
self.engineTool.destroy();
// self.objectSpawner.destroy();
// self.videoplayer.destroy();
self.allocator.destroy(self);
}
pub fn main() anyerror!void {
var spec = try backlog.getSpec("sampleGame");
// try spec.put("useGPA", .{ .boolean = false });
_ = backlog.startEngine(&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;