aboutsummaryrefslogtreecommitdiff
path: root/src/raycast.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/raycast.zig')
-rw-r--r--src/raycast.zig51
1 files changed, 31 insertions, 20 deletions
diff --git a/src/raycast.zig b/src/raycast.zig
index dec6b46..6acc16b 100644
--- a/src/raycast.zig
+++ b/src/raycast.zig
@@ -27,10 +27,11 @@ pub const RenderWallFunction: type = fn (
sprite: Sprite,
col: i32, // which column we're in
top: f32, // top of wall
- length: f32,
+ draw_frac: f32,
+ length: f32, // length of slice to be drawn
texfrac: f32,
texture: u8, // which texture index
-) anyerror!void; // TODO: narrow this error type.
+) void;
pub const Player = struct {
pos_x: f32,
@@ -87,7 +88,7 @@ pub const Player = struct {
map: Map,
// the abstract the rendering call
renderWall: RenderWallFunction,
- ) !void {
+ ) void {
const floor = std.math.floor;
var col: i32 = 0;
@@ -133,6 +134,7 @@ pub const Player = struct {
var distance: f32 = 0;
var still_drawing = true;
+ var highest_point: f32 = 0;
var horizontal_hit: bool = undefined;
while (still_drawing) {
@@ -153,28 +155,37 @@ pub const Player = struct {
var cell = map.lookup(ipos_x, ipos_y);
- // We have a wall to draw
- if (cell.height > 0) {
- // before we correct the distance to be the perpedicular
- // distance from the plane of projection, we need to use it
- // to calculate the fractional part of the relevant
- // coordinate
+ // the correct distance is the shortest distance from the plane
+ // of projection to the point, that is, perpendicular distance
+ const perp_distance = distance * std.math.cos(self.ang - ra);
+
+ // project the top of the wall
+ const top = self.plane_height / 2 + self.plane_dist * (cell.height - self.height) / perp_distance;
+
+ // We have a wall to draw if it protrudes above what we have so far drawn
+ if (top > highest_point) {
+
+ // did we extend beyond the top of the plane?
+ if (top > self.plane_height) still_drawing = false;
+
+ // compute the height of this wall
+ const total_length = self.plane_dist * cell.height / perp_distance;
+
+ // as well as the fraction we'll be drawing
+ const draw_frac = std.math.min(1, (top - highest_point) / total_length);
+
+ // we need the raw Euclidean distance to calculate the
+ // fractional part of the relevant coordinate for texture
+ // mapping of the walls
const hit_coordinate = if (horizontal_hit) distance * cosra + self.pos_x else distance * sinra + self.pos_y;
var texfrac = std.math.modf(hit_coordinate).fpart;
- // we also want to be sure that we're consistently orienting these, say clockwise
+ // we also want to be sure that we're consistently orienting
+ // textures, in this case clockwise
if ((horizontal_hit and sinra < 0) or (!horizontal_hit and cosra > 0)) texfrac = 1 - texfrac;
- // now correct the distance to be the shortest distance from
- // the plane to the point, that is, perpendicular distance
- distance *= std.math.cos(self.ang - ra);
-
- // project the top of the wall
- const top = self.plane_height / 2 + self.plane_dist * (cell.height - self.height) / distance;
- const height = self.plane_dist * cell.height / distance;
-
- try renderWall(window, sprite, col, top, height, texfrac, cell.wall_texture);
+ renderWall(window, sprite, col, top, total_length, draw_frac, texfrac, cell.wall_texture);
- still_drawing = false;
+ highest_point = top;
}
}
}