Separate and improve player movement
This commit is contained in:
109
src/Game.zig
109
src/Game.zig
@@ -15,6 +15,7 @@ const Engine = @import("engine/Engine.zig");
|
|||||||
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
const GenericBuffer = @import("engine/GenericBuffer.zig").GenericBuffer;
|
||||||
const StagingBuffer = @import("engine/StagingBuffer.zig");
|
const StagingBuffer = @import("engine/StagingBuffer.zig");
|
||||||
const Swapchain = @import("engine/Swapchain.zig");
|
const Swapchain = @import("engine/Swapchain.zig");
|
||||||
|
const Player = @import("Player.zig");
|
||||||
const Interator2 = math.Interator2;
|
const Interator2 = math.Interator2;
|
||||||
const Matrix4x4 = math.Matrix4x4;
|
const Matrix4x4 = math.Matrix4x4;
|
||||||
const Quaternion = math.Quaternion;
|
const Quaternion = math.Quaternion;
|
||||||
@@ -128,16 +129,7 @@ materials: Materials,
|
|||||||
textures: Textures,
|
textures: Textures,
|
||||||
chunks: std.AutoHashMapUnmanaged([3]i16, Chunk),
|
chunks: std.AutoHashMapUnmanaged([3]i16, Chunk),
|
||||||
|
|
||||||
camera_position: Vector3 = .init(0, 0, 1.62),
|
player: Player,
|
||||||
camera_pitch: f32 = 0,
|
|
||||||
camera_yaw: f32 = 0,
|
|
||||||
|
|
||||||
input_forwards: bool = false,
|
|
||||||
input_backwards: bool = false,
|
|
||||||
input_left: bool = false,
|
|
||||||
input_right: bool = false,
|
|
||||||
input_up: bool = false,
|
|
||||||
input_down: bool = false,
|
|
||||||
|
|
||||||
const max_textures = 1024;
|
const max_textures = 1024;
|
||||||
const max_point_lights = 1024;
|
const max_point_lights = 1024;
|
||||||
@@ -145,12 +137,6 @@ const max_directional_lights = 4;
|
|||||||
const chunk_descriptor_pool = 512;
|
const chunk_descriptor_pool = 512;
|
||||||
|
|
||||||
const camera_near_plane = 0.1;
|
const camera_near_plane = 0.1;
|
||||||
const camera_vertical_fov_deg = 80.0;
|
|
||||||
const camera_half_vertical_fov_rad = 0.5 * camera_vertical_fov_deg * std.math.rad_per_deg;
|
|
||||||
const camera_mouse_sensitivity = 0.002;
|
|
||||||
|
|
||||||
const player_horizontal_speed = 11.0;
|
|
||||||
const player_vertical_speed = 7.49;
|
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain) !Game {
|
pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain) !Game {
|
||||||
var materials = try Materials.init(engine, allocator);
|
var materials = try Materials.init(engine, allocator);
|
||||||
@@ -664,7 +650,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const camera_position = Vector3.init(0, 0, @as(f32, @floatFromInt(worldHeightI(.zero))) + 0.5 + 1.62);
|
const player_position = Vector3.init(0, 0, @as(f32, @floatFromInt(worldHeightI(.zero))) + 0.5);
|
||||||
|
|
||||||
var chunk_it = chunks.iterator();
|
var chunk_it = chunks.iterator();
|
||||||
while (chunk_it.next()) |entry| {
|
while (chunk_it.next()) |entry| {
|
||||||
@@ -724,7 +710,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
|||||||
.textures = textures,
|
.textures = textures,
|
||||||
.chunks = chunks,
|
.chunks = chunks,
|
||||||
|
|
||||||
.camera_position = camera_position,
|
.player = .init(player_position, 0, 0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,34 +751,25 @@ pub fn deinit(self: *Game) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(self: *Game, dt: f32) void {
|
pub fn update(self: *Game, dt: f32) void {
|
||||||
const camera_d = Vector2
|
self.player.update(dt);
|
||||||
.init(
|
|
||||||
@as(f32, @floatFromInt(@intFromBool(self.input_right))) - @as(f32, @floatFromInt(@intFromBool(self.input_left))),
|
|
||||||
@as(f32, @floatFromInt(@intFromBool(self.input_forwards))) - @as(f32, @floatFromInt(@intFromBool(self.input_backwards))),
|
|
||||||
)
|
|
||||||
.rotate(self.camera_yaw)
|
|
||||||
.mulScalar(player_horizontal_speed)
|
|
||||||
.asVector3(player_vertical_speed * (@as(f32, @floatFromInt(@intFromBool(self.input_up))) - @as(f32, @floatFromInt(@intFromBool(self.input_down)))))
|
|
||||||
.mulScalar(dt);
|
|
||||||
|
|
||||||
self.camera_position = Vector3.add(self.camera_position, camera_d);
|
|
||||||
|
|
||||||
const framebuffer_size = Vector2.init(
|
const framebuffer_size = Vector2.init(
|
||||||
@floatFromInt(self.swapchain.extent.width),
|
@floatFromInt(self.swapchain.extent.width),
|
||||||
@floatFromInt(self.swapchain.extent.height),
|
@floatFromInt(self.swapchain.extent.height),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const camera_position = self.player.position.add(.init(0, Player.camera_height, 0));
|
||||||
const camera_rotation = Quaternion.mulQuaternion(
|
const camera_rotation = Quaternion.mulQuaternion(
|
||||||
.initRotationXY(self.camera_yaw),
|
.initRotationXY(self.player.yaw_rad),
|
||||||
.initRotationYZ(self.camera_pitch),
|
.initRotationYZ(self.player.pitch_rad),
|
||||||
);
|
);
|
||||||
const camera_aspect_ratio = framebuffer_size.getX() / framebuffer_size.getY();
|
const camera_aspect_ratio = framebuffer_size.getX() / framebuffer_size.getY();
|
||||||
const camera_yscale = 1.0 / @tan(camera_half_vertical_fov_rad);
|
const camera_yscale = 1.0 / @tan(0.5 * self.player.vertical_fov_deg * std.math.rad_per_deg);
|
||||||
const camera_xscale = camera_yscale / camera_aspect_ratio;
|
const camera_xscale = camera_yscale / camera_aspect_ratio;
|
||||||
|
|
||||||
const matrix_ws_to_vs = Matrix4x4.mulMatrix(
|
const matrix_ws_to_vs = Matrix4x4.mulMatrix(
|
||||||
Matrix4x4.initRotation(camera_rotation.conjugate()),
|
Matrix4x4.initRotation(camera_rotation.conjugate()),
|
||||||
Matrix4x4.initTranslation(self.camera_position.negate()),
|
Matrix4x4.initTranslation(camera_position.negate()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
@@ -832,78 +809,26 @@ pub fn update(self: *Game, dt: f32) void {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onKeyDown(self: *Game, key_code: glfw.Key, mods: glfw.Mods) void {
|
pub fn onKeyDown(self: *Game, key: glfw.Key) void {
|
||||||
const no_mods = @as(c_int, @bitCast(mods)) == 0;
|
self.player.onKeyDown(key);
|
||||||
|
|
||||||
if (key_code == .escape and no_mods) {
|
|
||||||
self.engine.mode.surface.window.setShouldClose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_code == .w) {
|
|
||||||
self.input_forwards = true;
|
|
||||||
self.input_backwards = false;
|
|
||||||
}
|
|
||||||
if (key_code == .s) {
|
|
||||||
self.input_backwards = true;
|
|
||||||
self.input_forwards = false;
|
|
||||||
}
|
|
||||||
if (key_code == .a) {
|
|
||||||
self.input_left = true;
|
|
||||||
self.input_right = false;
|
|
||||||
}
|
|
||||||
if (key_code == .d) {
|
|
||||||
self.input_right = true;
|
|
||||||
self.input_left = false;
|
|
||||||
}
|
|
||||||
if (key_code == .space) {
|
|
||||||
self.input_up = true;
|
|
||||||
}
|
|
||||||
if (key_code == .left_shift) {
|
|
||||||
self.input_down = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onKeyUp(self: *Game, key_code: glfw.Key, mods: glfw.Mods) void {
|
pub fn onKeyUp(self: *Game, key: glfw.Key) void {
|
||||||
_ = mods;
|
self.player.onKeyUp(key);
|
||||||
|
|
||||||
if (key_code == .w) {
|
|
||||||
self.input_forwards = false;
|
|
||||||
}
|
|
||||||
if (key_code == .s) {
|
|
||||||
self.input_backwards = false;
|
|
||||||
}
|
|
||||||
if (key_code == .a) {
|
|
||||||
self.input_left = false;
|
|
||||||
}
|
|
||||||
if (key_code == .d) {
|
|
||||||
self.input_right = false;
|
|
||||||
}
|
|
||||||
if (key_code == .space) {
|
|
||||||
self.input_up = false;
|
|
||||||
}
|
|
||||||
if (key_code == .left_shift) {
|
|
||||||
self.input_down = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onMouseMove(self: *Game, dx: f32, dy: f32) void {
|
pub fn onMouseMove(self: *Game, dx: f32, dy: f32) void {
|
||||||
self.camera_pitch -= dy * camera_mouse_sensitivity;
|
self.player.onMouseMove(dx, dy);
|
||||||
self.camera_yaw -= dx * camera_mouse_sensitivity;
|
|
||||||
|
|
||||||
self.camera_pitch = std.math.clamp(self.camera_pitch, -0.5 * std.math.pi, 0.5 * std.math.pi);
|
|
||||||
self.camera_yaw = @mod(self.camera_yaw, 2 * std.math.pi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onMouseDown(self: *Game, button: glfw.MouseButton, mods: glfw.Mods) void {
|
pub fn onMouseDown(self: *Game, button: glfw.MouseButton) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = button;
|
_ = button;
|
||||||
_ = mods;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onMouseUp(self: *Game, button: glfw.MouseButton, mods: glfw.Mods) void {
|
pub fn onMouseUp(self: *Game, button: glfw.MouseButton) void {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = button;
|
_ = button;
|
||||||
_ = mods;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(self: *Game) !void {
|
fn render(self: *Game) !void {
|
||||||
|
|||||||
135
src/Player.zig
Normal file
135
src/Player.zig
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
const Player = @This();
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const glfw = @import("zglfw");
|
||||||
|
const math = @import("math.zig");
|
||||||
|
|
||||||
|
const Vector2 = math.Vector2;
|
||||||
|
const Vector3 = math.Vector3;
|
||||||
|
|
||||||
|
const AxisState = enum {
|
||||||
|
none,
|
||||||
|
positive,
|
||||||
|
negative,
|
||||||
|
both_positive,
|
||||||
|
both_negative,
|
||||||
|
|
||||||
|
pub fn getComponent(self: AxisState) f32 {
|
||||||
|
return switch (self) {
|
||||||
|
.none => 0,
|
||||||
|
.positive, .both_positive => 1,
|
||||||
|
.negative, .both_negative => -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Axis = struct {
|
||||||
|
state: AxisState = .none,
|
||||||
|
positive_key: glfw.Key,
|
||||||
|
negative_key: glfw.Key,
|
||||||
|
|
||||||
|
pub fn init(positive_key: glfw.Key, negative_key: glfw.Key) Axis {
|
||||||
|
return .{
|
||||||
|
.positive_key = positive_key,
|
||||||
|
.negative_key = negative_key,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onKeyDown(self: *Axis, key_code: glfw.Key) void {
|
||||||
|
if (key_code == self.positive_key) {
|
||||||
|
switch (self.state) {
|
||||||
|
.none => self.state = .positive,
|
||||||
|
.negative => self.state = .both_positive,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
} else if (key_code == self.negative_key) {
|
||||||
|
switch (self.state) {
|
||||||
|
.none => self.state = .negative,
|
||||||
|
.positive => self.state = .both_negative,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onKeyUp(self: *Axis, key_code: glfw.Key) void {
|
||||||
|
if (key_code == self.positive_key) {
|
||||||
|
switch (self.state) {
|
||||||
|
.positive => self.state = .none,
|
||||||
|
.both_positive, .both_negative => self.state = .negative,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
} else if (key_code == self.negative_key) {
|
||||||
|
switch (self.state) {
|
||||||
|
.negative => self.state = .none,
|
||||||
|
.both_positive, .both_negative => self.state = .positive,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getComponent(self: Axis) f32 {
|
||||||
|
return self.state.getComponent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
position: Vector3,
|
||||||
|
pitch_rad: f32,
|
||||||
|
yaw_rad: f32,
|
||||||
|
|
||||||
|
x_input: Axis = .init(.d, .a),
|
||||||
|
y_input: Axis = .init(.w, .s),
|
||||||
|
z_input: Axis = .init(.space, .left_shift),
|
||||||
|
|
||||||
|
mouse_sensitivity: f32 = 0.002,
|
||||||
|
vertical_fov_deg: f32 = 80,
|
||||||
|
|
||||||
|
pub const camera_height = 1.62;
|
||||||
|
|
||||||
|
pub const horizontal_speed = 11.0;
|
||||||
|
pub const vertical_speed = 7.49;
|
||||||
|
|
||||||
|
pub const min_pitch_rad = -0.5 * std.math.pi;
|
||||||
|
pub const max_pitch_rad = 0.5 * std.math.pi;
|
||||||
|
|
||||||
|
pub fn init(position: Vector3, pitch_rad: f32, yaw_rad: f32) Player {
|
||||||
|
return .{
|
||||||
|
.position = position,
|
||||||
|
.pitch_rad = pitch_rad,
|
||||||
|
.yaw_rad = yaw_rad,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onKeyDown(self: *Player, key: glfw.Key) void {
|
||||||
|
self.x_input.onKeyDown(key);
|
||||||
|
self.y_input.onKeyDown(key);
|
||||||
|
self.z_input.onKeyDown(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onKeyUp(self: *Player, key: glfw.Key) void {
|
||||||
|
self.x_input.onKeyUp(key);
|
||||||
|
self.y_input.onKeyUp(key);
|
||||||
|
self.z_input.onKeyUp(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onMouseMove(self: *Player, dx: f32, dy: f32) void {
|
||||||
|
self.pitch_rad = std.math.clamp(self.pitch_rad - dy * self.mouse_sensitivity, min_pitch_rad, max_pitch_rad);
|
||||||
|
self.yaw_rad = @mod(self.yaw_rad - dx * self.mouse_sensitivity, std.math.tau);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(self: *Player, dt: f32) void {
|
||||||
|
var horizontal_input_vector = Vector2
|
||||||
|
.init(self.x_input.getComponent(), self.y_input.getComponent())
|
||||||
|
.rotate(self.yaw_rad);
|
||||||
|
const horizontal_input_vector_len_squared = horizontal_input_vector.lenSquared();
|
||||||
|
if (horizontal_input_vector_len_squared > 1) {
|
||||||
|
horizontal_input_vector = horizontal_input_vector.divScalar(horizontal_input_vector_len_squared);
|
||||||
|
}
|
||||||
|
const vertical_input_vector = self.z_input.getComponent();
|
||||||
|
|
||||||
|
const horizontal_velocity = horizontal_input_vector.mulScalar(horizontal_speed);
|
||||||
|
const vertical_velocity = vertical_input_vector * vertical_speed;
|
||||||
|
|
||||||
|
const displacement = horizontal_velocity.asVector3(vertical_velocity).mulScalar(dt);
|
||||||
|
|
||||||
|
self.position = Vector3.add(self.position, displacement);
|
||||||
|
}
|
||||||
12
src/main.zig
12
src/main.zig
@@ -97,7 +97,7 @@ const CallbackContext = struct {
|
|||||||
cursor_last_ypos: f64,
|
cursor_last_ypos: f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn keyCallback(window: *glfw.Window, key_code: glfw.Key, _: c_int, action: glfw.Action, mods: glfw.Mods) callconv(.c) void {
|
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);
|
const maybe_ctx = window.getUserPointer(CallbackContext);
|
||||||
|
|
||||||
if (key_code == .escape and action == .press and (window.getInputMode(.cursor) catch .normal) == .disabled) {
|
if (key_code == .escape and action == .press and (window.getInputMode(.cursor) catch .normal) == .disabled) {
|
||||||
@@ -114,8 +114,8 @@ fn keyCallback(window: *glfw.Window, key_code: glfw.Key, _: c_int, action: glfw.
|
|||||||
if (maybe_ctx) |ctx| {
|
if (maybe_ctx) |ctx| {
|
||||||
if (ctx.focused) {
|
if (ctx.focused) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.press => ctx.game.onKeyDown(key_code, mods),
|
.press => ctx.game.onKeyDown(key_code),
|
||||||
.release => ctx.game.onKeyUp(key_code, mods),
|
.release => ctx.game.onKeyUp(key_code),
|
||||||
.repeat => {},
|
.repeat => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ fn cursorPosCallback(window: *glfw.Window, cursor_xpos: f64, cursor_ypos: f64) c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouseButtonCallback(window: *glfw.Window, button: glfw.MouseButton, action: glfw.Action, mods: glfw.Mods) callconv(.c) void {
|
fn mouseButtonCallback(window: *glfw.Window, button: glfw.MouseButton, action: glfw.Action, _: glfw.Mods) callconv(.c) void {
|
||||||
const maybe_ctx = window.getUserPointer(CallbackContext);
|
const maybe_ctx = window.getUserPointer(CallbackContext);
|
||||||
|
|
||||||
if (button == .left and action == .press and (window.getInputMode(.cursor) catch .normal) == .normal) {
|
if (button == .left and action == .press and (window.getInputMode(.cursor) catch .normal) == .normal) {
|
||||||
@@ -151,8 +151,8 @@ fn mouseButtonCallback(window: *glfw.Window, button: glfw.MouseButton, action: g
|
|||||||
if (maybe_ctx) |ctx| {
|
if (maybe_ctx) |ctx| {
|
||||||
if (ctx.focused) {
|
if (ctx.focused) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.press => ctx.game.onMouseDown(button, mods),
|
.press => ctx.game.onMouseDown(button),
|
||||||
.release => ctx.game.onMouseUp(button, mods),
|
.release => ctx.game.onMouseUp(button),
|
||||||
.repeat => {},
|
.repeat => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user