aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortslil clingman <>2021-09-12 21:40:58 -0400
committertslil clingman <>2021-09-12 21:40:58 -0400
commitd89f038b7a5eb42dd48d729d8808747d5cbc182b (patch)
tree2f726aef25edaf1723e62ec99e19c425afa37cdf
parentb674e201cecf38ae719f76c0d159d8cbf00158ed (diff)
Walk bob and collision detection
-rw-r--r--src/level.zig3
-rw-r--r--src/main.zig29
-rw-r--r--src/raycast.zig52
3 files changed, 64 insertions, 20 deletions
diff --git a/src/level.zig b/src/level.zig
index 610eb7b..1d61a02 100644
--- a/src/level.zig
+++ b/src/level.zig
@@ -62,8 +62,7 @@ pub const Map = struct {
}
pub fn lookup(self: Map, x: i32, y: i32) Cell {
- // live dangerously, no bounds check
- std.debug.assert(x >= 0 and y >= 0); // compiler hint?
+ // std.debug.assert(x >= 0 and y >= 0); // would this work as a compiler hint?
return self.cells.items[@intCast(u32, y) * self.width + @intCast(u32, x)];
}
};
diff --git a/src/main.zig b/src/main.zig
index c44b5e6..ec47f86 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -133,24 +133,33 @@ pub fn main() !void {
if (isKeyPressed(.R)) player.ang += rotation;
if (isKeyPressed(.T)) player.ang -= rotation;
+ const cos = std.math.cos(player.ang);
+ const sin = std.math.sin(player.ang);
+
player.acc_x = 0;
player.acc_y = 0;
- const acc_mag = 50;
+ const acc_mag = 30;
if (isKeyPressed(.Right)) {
- player.acc_x += std.math.cos(player.ang - PI / 2.0) * acc_mag;
- player.acc_y += std.math.sin(player.ang - PI / 2.0) * acc_mag;
+ player.acc_x += sin;
+ player.acc_y -= cos;
}
if (isKeyPressed(.Left)) {
- player.acc_x -= std.math.cos(player.ang - PI / 2.0) * acc_mag;
- player.acc_y -= std.math.sin(player.ang - PI / 2.0) * acc_mag;
+ player.acc_x -= sin;
+ player.acc_y += cos;
}
if (isKeyPressed(.Up) or isKeyPressed(.F)) {
- player.acc_x += std.math.cos(player.ang) * acc_mag;
- player.acc_y += std.math.sin(player.ang) * acc_mag;
+ player.acc_x += cos;
+ player.acc_y += sin;
}
if (isKeyPressed(.Down) or isKeyPressed(.S)) {
- player.acc_x -= std.math.cos(player.ang) * acc_mag;
- player.acc_y -= std.math.sin(player.ang) * acc_mag;
+ player.acc_x -= cos;
+ player.acc_y -= sin;
+ }
+ // normalise
+ const a = std.math.sqrt(player.acc_x * player.acc_x + player.acc_y * player.acc_y);
+ if (a > 0) {
+ player.acc_x *= acc_mag / a;
+ player.acc_y *= acc_mag / a;
}
// First the background
@@ -177,6 +186,6 @@ pub fn main() !void {
window.display();
- player.tick();
+ player.tick(map);
}
}
diff --git a/src/raycast.zig b/src/raycast.zig
index 77a9ef0..6082b74 100644
--- a/src/raycast.zig
+++ b/src/raycast.zig
@@ -80,6 +80,8 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
height: f32 = 2.0 * (1.8 / 2.5), // TODO
z_buffer: std.BoundedArray(f32, PlanePixels),
+ anim_step: f32 = 0,
+
// standing still at the given location, looking in direction ang
pub fn new(pos_x: f32, pos_y: f32, ang: f32) !@This() {
const infs = [_]f32{std.math.inf(f32)} ** PlanePixels;
@@ -92,21 +94,55 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
};
}
- pub fn tick(self: *@This()) void {
+ pub fn tick(self: *@This(), map: level.Map) void {
const dt = 1 / 30.0;
const v_min = 0.8;
- const v_decay = 1.25;
+ const v_decay = 1 / 1.25;
+
+ var next_x = self.pos_x + self.vel_x * dt;
+ var next_y = self.pos_y + self.vel_y * dt;
- self.pos_x += self.vel_x * dt;
- self.pos_y += self.vel_y * dt;
+ // Collision detection
+ const min_dist: f32 = 0.1;
+ const fx = std.math.floor(self.pos_x);
+ const fy = std.math.floor(self.pos_y);
+ const ix = @floatToInt(i32, fx);
+ const iy = @floatToInt(i32, fy);
+ const nix = @floatToInt(i32, std.math.floor(next_x + if (self.vel_x > 0) min_dist else -min_dist));
+ const niy = @floatToInt(i32, std.math.floor(next_y + if (self.vel_y > 0) min_dist else -min_dist));
- self.vel_x /= v_decay;
- if (std.math.fabs(self.vel_x) < v_min) self.vel_x = 0;
- self.vel_y /= v_decay;
- if (std.math.fabs(self.vel_y) < v_min) self.vel_y = 0;
+ if (!map.inBounds(nix, iy) or map.lookup(nix, iy).height > 0) {
+ next_x = fx + if (self.vel_x > 0) 1 - min_dist else min_dist;
+ self.vel_x = 0;
+ self.acc_x = 0;
+ }
+
+ if (!map.inBounds(ix, niy) or map.lookup(ix, niy).height > 0) {
+ next_y = fy + if (self.vel_y > 0) 1 - min_dist else min_dist;
+ self.vel_y = 0;
+ self.acc_y = 0;
+ }
+ // Update position
+ self.pos_x = next_x;
+ self.pos_y = next_y;
+
+ // Update velocity
self.vel_x += self.acc_x * dt;
self.vel_y += self.acc_y * dt;
+
+ const vd = v_decay * std.math.sqrt(self.vel_x * self.vel_x + self.vel_y * self.vel_y);
+ if (vd < v_min) {
+ self.vel_x = 0;
+ self.vel_y = 0;
+ } else {
+ // If we're moving update our animation state
+ self.anim_step += 1;
+ self.height -= std.math.sin(self.anim_step / 10 * std.math.pi) * 0.015;
+
+ self.vel_x *= v_decay;
+ self.vel_y *= v_decay;
+ }
}
pub fn renderWorld(