Keyboard input, translation, time

This commit is contained in:
duck
2025-05-27 18:55:25 +05:00
parent a7afe41a70
commit 1e454ba428
6 changed files with 169 additions and 6 deletions

View File

@@ -69,15 +69,33 @@ pub fn init(controller: *Controller, graphics: *Graphics) !void {
pub fn deinit() void {} pub fn deinit() void {}
pub fn update(cube: *Cube, mouse: *Game.Mouse, graphics: *Graphics) void { pub fn update(
mouse: *Game.Mouse,
keyboard: *Game.Keyboard,
graphics: *Graphics,
time: *Game.Time,
) void {
if (keyboard.is_pressed(sdl.SCANCODE_W)) {
graphics.camera.transform.translateLocal(.{ 0.0, 0.0, 5.0 * time.delta });
}
if (keyboard.is_pressed(sdl.SCANCODE_S)) {
graphics.camera.transform.translateLocal(.{ 0.0, 0.0, -5.0 * time.delta });
}
if (keyboard.is_pressed(sdl.SCANCODE_D)) {
graphics.camera.transform.translateLocal(.{ 5.0 * time.delta, 0.0, 0.0 });
}
if (keyboard.is_pressed(sdl.SCANCODE_A)) {
graphics.camera.transform.translateLocal(.{ -5.0 * time.delta, 0.0, 0.0 });
}
if (@abs(mouse.dx) < 0.01 and @abs(mouse.dy) < 0.01) return; if (@abs(mouse.dx) < 0.01 and @abs(mouse.dy) < 0.01) return;
const delta, const length = Graphics.Transform.extractNormal(.{ -mouse.dy, -mouse.dx, 0.0 }); const delta, const length = Graphics.Transform.extractNormal(.{ mouse.dy, mouse.dx, 0.0 });
const rot = Graphics.Transform.rotationByAxis( const rot = Graphics.Transform.rotationByAxis(
delta, delta,
length * std.math.pi / @as(f32, @floatFromInt(graphics.window_size[1])) * 2.0, length * std.math.pi / @as(f32, @floatFromInt(graphics.window_size[1])) * 2.0,
); );
cube.transform.rotate(rot); graphics.camera.transform.rotateLocal(rot);
} }
pub fn draw(cube: *Cube, graphics: *Graphics) !void { pub fn draw(cube: *Cube, graphics: *Graphics) !void {

View File

@@ -9,8 +9,10 @@ const Graphics = @import("graphics.zig");
// TODO: // TODO:
// - Do something about deallocating `Resource`s when `Graph` fails // - Do something about deallocating `Resource`s when `Graph` fails
const RunInfo = struct { running: bool }; pub const RunInfo = struct { running: bool };
pub const Mouse = struct { x: f32, y: f32, dx: f32, dy: f32 }; pub const Mouse = @import("mouse.zig");
pub const Keyboard = @import("keyboard.zig");
pub const Time = @import("time.zig");
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
graph: Graph, graph: Graph,
@@ -30,6 +32,11 @@ pub fn init(alloc: std.mem.Allocator) GameError!Self {
.dx = 0.0, .dx = 0.0,
.dy = 0.0, .dy = 0.0,
}); });
controller.addResource(Keyboard{});
controller.addResource(Time{
.delta = 0.0,
.now = 0,
});
controller.queue(debug_scene.init); controller.queue(debug_scene.init);
try graph.freeController(controller); try graph.freeController(controller);
@@ -54,6 +61,13 @@ pub fn run(self: *Self) GameError!void {
break; break;
} }
var current_time: sdl.Time = undefined;
if (sdl.GetCurrentTime(&current_time)) {
const time = self.graph.getResource(Time).?;
time.delta = @as(f32, @floatFromInt(current_time - time.now)) * 0.000000001;
time.now = current_time;
}
var controller = try self.graph.getController(); var controller = try self.graph.getController();
controller.queue(.{ controller.queue(.{
.events = processEvents, .events = processEvents,
@@ -84,9 +98,15 @@ fn clean(graphics: *Graphics) !void {
// TODO: Also remove the resource // TODO: Also remove the resource
} }
fn processEvents(graphics: *Graphics, run_info: *RunInfo, mouse: *Mouse) GameError!void { fn processEvents(
graphics: *Graphics,
run_info: *RunInfo,
mouse: *Mouse,
keyboard: *Keyboard,
) GameError!void {
mouse.dx = 0.0; mouse.dx = 0.0;
mouse.dy = 0.0; mouse.dy = 0.0;
keyboard.reset();
sdl.PumpEvents(); sdl.PumpEvents();
while (true) { while (true) {
@@ -109,6 +129,14 @@ fn processEvents(graphics: *Graphics, run_info: *RunInfo, mouse: *Mouse) GameErr
mouse.dx += event.motion.xrel; mouse.dx += event.motion.xrel;
mouse.dy += event.motion.yrel; mouse.dy += event.motion.yrel;
}, },
sdl.EVENT_KEY_DOWN => {
if (event.key.windowID != sdl.GetWindowID(graphics.window)) continue;
keyboard.press(event.key.scancode);
},
sdl.EVENT_KEY_UP => {
if (event.key.windowID != sdl.GetWindowID(graphics.window)) continue;
keyboard.release(event.key.scancode);
},
else => {}, else => {},
} }
} }

View File

@@ -13,6 +13,7 @@ scale: Scale = @splat(1.0),
pub fn matrix(transform: Transform) TMatrix { pub fn matrix(transform: Transform) TMatrix {
@setFloatMode(.optimized); @setFloatMode(.optimized);
const r = rotationMatrix(transform.rotation); const r = rotationMatrix(transform.rotation);
const sx, const sy, const sz = transform.scale; const sx, const sy, const sz = transform.scale;
return .{ return .{
@@ -25,6 +26,7 @@ pub fn matrix(transform: Transform) TMatrix {
pub fn inverseMatrix(transform: Transform) TMatrix { pub fn inverseMatrix(transform: Transform) TMatrix {
@setFloatMode(.optimized); @setFloatMode(.optimized);
const r = rotationMatrix(flipRotation(transform.rotation)); const r = rotationMatrix(flipRotation(transform.rotation));
const tx, const ty, const tz = transform.position; const tx, const ty, const tz = transform.position;
const sx = 1.0 / transform.scale[0]; const sx = 1.0 / transform.scale[0];
@@ -47,11 +49,49 @@ pub fn inverseMatrix(transform: Transform) TMatrix {
}; };
} }
pub fn translate(transform: *Transform, translation: Position) void {
@setFloatMode(.optimized);
transform.position += translation;
}
pub fn translateLocal(transform: *Transform, translation: Position) void {
@setFloatMode(.optimized);
const a = transform.rotation[0];
const b = transform.rotation[1];
const c = transform.rotation[2];
const d = transform.rotation[3];
const s = 2.0 / (a * a + b * b + c * c + d * d);
const bs = b * s;
const cs = c * s;
const ds = d * s;
const ab = a * bs;
const ac = a * cs;
const ad = a * ds;
const bb = b * bs;
const bc = b * cs;
const bd = b * ds;
const cc = c * cs;
const cd = c * ds;
const dd = d * ds;
transform.position[0] += translation[0] * (1 - cc - dd) + translation[1] * (bc - ad) + translation[2] * (bd + ac);
transform.position[1] += translation[0] * (bc + ad) + translation[1] * (1 - bb - dd) + translation[2] * (cd - ab);
transform.position[2] += translation[0] * (bd - ac) + translation[1] * (cd + ab) + translation[2] * (1 - bb - cc);
}
pub fn rotate(transform: *Transform, rotation: Rotation) void { pub fn rotate(transform: *Transform, rotation: Rotation) void {
@setFloatMode(.optimized);
transform.rotation = normalizeRotation(combineRotations(transform.rotation, rotation)); transform.rotation = normalizeRotation(combineRotations(transform.rotation, rotation));
} }
pub fn rotateLocal(transform: *Transform, rotation: Rotation) void { pub fn rotateLocal(transform: *Transform, rotation: Rotation) void {
@setFloatMode(.optimized);
transform.rotation = normalizeRotation(combineRotations(rotation, transform.rotation)); transform.rotation = normalizeRotation(combineRotations(rotation, transform.rotation));
} }

69
src/keyboard.zig Normal file
View File

@@ -0,0 +1,69 @@
const sdl = @import("sdl");
const BUFFER_SIZE = 16;
const ZERO = sdl.SCANCODE_UNKNOWN;
just_pressed: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE,
pressed: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE,
just_released: [BUFFER_SIZE]sdl.Scancode = .{ZERO} ** BUFFER_SIZE,
const Self = @This();
pub fn reset(self: *Self) void {
self.just_pressed = .{ZERO} ** BUFFER_SIZE;
self.just_released = .{ZERO} ** BUFFER_SIZE;
}
pub fn press(self: *Self, code: sdl.Scancode) void {
for (self.pressed) |pressed| {
if (pressed == code) return;
}
for (&self.pressed) |*pressed| {
if (pressed.* == ZERO) {
pressed.* = code;
break;
}
}
for (self.just_pressed) |just_pressed| {
if (just_pressed == code) return;
}
for (&self.just_pressed) |*just_pressed| {
if (just_pressed.* == ZERO) {
just_pressed.* = code;
break;
}
}
}
pub fn release(self: *Self, code: sdl.Scancode) void {
for (&self.pressed) |*pressed| {
if (pressed.* == code) {
pressed.* = ZERO;
break;
}
}
for (self.just_released) |just_released| {
if (just_released == code) return;
}
for (&self.just_released) |*just_released| {
if (just_released.* == ZERO) {
just_released.* = code;
break;
}
}
}
pub fn is_just_pressed(self: *Self, code: sdl.Scancode) bool {
for (self.just_pressed) |just_pressed| {
if (just_pressed == code) return true;
}
return false;
}
pub fn is_pressed(self: *Self, code: sdl.Scancode) bool {
for (self.pressed) |pressed| {
if (pressed == code) return true;
}
return false;
}
pub fn is_just_released(self: *Self, code: sdl.Scancode) bool {
for (self.just_released) |just_released| {
if (just_released == code) return true;
}
return false;
}

4
src/mouse.zig Normal file
View File

@@ -0,0 +1,4 @@
x: f32,
y: f32,
dx: f32,
dy: f32,

4
src/time.zig Normal file
View File

@@ -0,0 +1,4 @@
const sdl = @import("sdl");
delta: f32,
now: sdl.Time,