diff options
Diffstat (limited to 'src/raycast.zig')
| -rw-r--r-- | src/raycast.zig | 51 |
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; } } } |
