From 9000c2e9f95438e53c8b1e0110a88db7b49d8077 Mon Sep 17 00:00:00 2001 From: tslil clingman <> Date: Mon, 20 Sep 2021 20:54:57 -0400 Subject: Render by writing pixels, instead of using hard. accel. sprites --- src/constants.zig | 4 ++-- src/main.zig | 11 +++-------- src/player.zig | 48 +++++++++++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/constants.zig b/src/constants.zig index 1ca0c4f..d363af5 100644 --- a/src/constants.zig +++ b/src/constants.zig @@ -18,8 +18,8 @@ pub const ScreenWidth: f32 = 1024; pub const ScreenHeight: f32 = 768; -pub const PlaneWidth = 320; -pub const PlaneHeight = 240; +pub const PlaneWidth = 640; +pub const PlaneHeight = 480; pub const HFact = ScreenWidth / PlaneWidth; pub const VFact = ScreenHeight / PlaneHeight; diff --git a/src/main.zig b/src/main.zig index dc8b2b9..283de07 100644 --- a/src/main.zig +++ b/src/main.zig @@ -86,13 +86,8 @@ pub fn main() !void { back_sprite.setScale(.{ .x = 4.0 * constants.ScreenWidth / constants.BackTextureWidth, .y = constants.ScreenHeight / constants.BackTextureHeight }); // Load wall textures - var wall_textures = try sf.Texture.createFromFile("walls.png"); - defer wall_textures.destroy(); - wall_textures.setRepeated(true); - wall_textures.setSmooth(false); // looks worse => better! - - var walls_sprite = try sf.Sprite.createFromTexture(wall_textures); - defer walls_sprite.destroy(); + var walls_image = try sf.Image.createFromFile("walls.png"); + defer walls_image.destroy(); // Load sprite textures var object_textures = try sf.Texture.createFromFile("objects.png"); @@ -176,8 +171,8 @@ pub fn main() !void { try player.renderWorld( window, - walls_sprite, objects_sprite, + walls_image, surfaces_image, rendered_surfaces_texture, rendered_surfaces_sprite, diff --git a/src/player.zig b/src/player.zig index 6082b74..992ef69 100644 --- a/src/player.zig +++ b/src/player.zig @@ -148,8 +148,8 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { pub fn renderWorld( self: *@This(), window: RenderWindow, - walls_sprite: Sprite, objects_sprite: Sprite, + walls_image: Image, surfaces_image: Image, rendered_surfaces_texture: Texture, rendered_surfaces_sprite: Sprite, @@ -165,7 +165,7 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { // then draw all the walls and populate the z_buffer, while also // rendering the surfaces below the horizon to the pixel array - self.renderCells(window, walls_sprite, surfaces_image, map, &pixels); + self.renderCells(walls_image, surfaces_image, map, &pixels); // then render the ceilings to our pixel array self.renderCeilingsToTexture(surfaces_image, map, &pixels); @@ -254,9 +254,8 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { fn renderCells( self: *@This(), - window: RenderWindow, - walls_sprite: Sprite, - floors_image: Image, + walls_image: Image, + surfaces_image: Image, map: level.Map, pixels: []Colour, ) void { @@ -347,13 +346,6 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { still_drawing = false; } - // compute the height of this wall - const total_length = PlaneDist * cell.height / distance; - - // as well as the fraction we'll be drawing - const draw_length = top - highest_point; - const draw_frac = cell.height * std.math.clamp(draw_length / total_length, 0, 1); - // we need the distance to calculate the fractional // part of the relevant coordinate for texture // mapping of the walls @@ -363,13 +355,31 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { // 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; + const texstrip = @floatToInt(c_uint, constants.TextureDim * texfrac); + + // which texture index? + const toff = cell.wall_texture * @floatToInt(c_uint, constants.TextureDim); + + // height of a unit-height wall at this distance + const nominal_length = PlaneDist / distance; + + // now we have what we need to draw the wall, and + // update the z-buffer + const constrained_top = std.math.min(top, PlaneHeight - 1); + var y = @floatToInt(i32, constrained_top); + var span = top - constrained_top; + while (y > @floatToInt(i32, highest_point)) : ({ + y -= 1; + span += 1; + }) { + const texel_y_frac = std.math.modf(span / nominal_length).fpart; + const ty = @floatToInt(c_uint, texel_y_frac * constants.TextureDim); + const texel = walls_image.getPixel(.{ .x = toff + texstrip, .y = ty }); + + const coord_flip_y = @floatToInt(usize, PlaneHeight) - @intCast(usize, y); + const pix_index = coord_flip_y * @floatToInt(usize, PlaneWidth) + col; + pixels[pix_index] = texel; - // draw the wall - renderSlice(window, walls_sprite, col, top, total_length / cell.height, draw_frac, texfrac, cell.wall_texture); - - // record that there's a wall here in the z_buffer - var y = @floatToInt(i32, std.math.min(top, PlaneHeight - 1)); - while (y > @floatToInt(i32, highest_point)) : (y -= 1) { const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + y); self.z_buffer.set(index, distance); } @@ -407,7 +417,7 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { const toff = cell.floor_texture * @floatToInt(c_uint, constants.TextureDim); const px = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sx.fpart)); const py = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sy.fpart)); - const val = floors_image.getPixel(.{ .x = toff + px, .y = py }); + const val = surfaces_image.getPixel(.{ .x = toff + px, .y = py }); pixels[itop * @floatToInt(usize, PlaneWidth) + col] = val; // record in the z_buffer only if we're above the floor! -- cgit v1.3.1