diff options
| -rw-r--r-- | src/main.zig | 10 | ||||
| -rw-r--r-- | src/player.zig | 72 |
2 files changed, 36 insertions, 46 deletions
diff --git a/src/main.zig b/src/main.zig index 283de07..3c95d20 100644 --- a/src/main.zig +++ b/src/main.zig @@ -90,12 +90,8 @@ pub fn main() !void { defer walls_image.destroy(); // Load sprite textures - var object_textures = try sf.Texture.createFromFile("objects.png"); - defer object_textures.destroy(); - object_textures.setSmooth(false); - - var objects_sprite = try sf.Sprite.createFromTexture(object_textures); - defer objects_sprite.destroy(); + var objects_image = try sf.Image.createFromFile("objects.png"); + defer objects_image.destroy(); // Load floor image var surfaces_image = try sf.Image.createFromFile("surfaces.png"); @@ -171,7 +167,7 @@ pub fn main() !void { try player.renderWorld( window, - objects_sprite, + objects_image, walls_image, surfaces_image, rendered_surfaces_texture, diff --git a/src/player.zig b/src/player.zig index 98f0b47..8ad3a1e 100644 --- a/src/player.zig +++ b/src/player.zig @@ -26,32 +26,6 @@ const Colour = @import("sfml").graphics.Color; const level = @import("level.zig"); const constants = @import("constants.zig"); -fn renderSlice( - window: RenderWindow, - sprite: Sprite, - col: i32, // which column - top: f32, // top of wall - height: f32, // how tall - draw_frac: f32, // how much to draw, as a fraction; > 1 means repeat texture - texfrac: f32, // how far along the texture - texture: u8, // which texture index -) void { - // we need ceil here so that we draw always to or past the edge of the screen - const draw_height = @floatToInt(c_int, std.math.ceil(draw_frac * constants.TextureDim)); - const total_height = height * constants.VFact; - - const xpos = @intToFloat(f32, col) * constants.HFact; - const ypos = constants.ScreenHeight / 2 + (constants.PlaneHeight / 2 - top) * constants.VFact; - - const tind = texture * @floatToInt(c_int, constants.TextureDim); - const left = tind + @floatToInt(c_int, texfrac * constants.TextureDim); - - sprite.setPosition(.{ .x = xpos, .y = ypos }); - sprite.setScale(.{ .x = constants.HFact, .y = total_height / constants.TextureDim }); - sprite.setTextureRect(.{ .top = 0, .left = left, .width = 1, .height = draw_height }); - window.draw(sprite, null); -} - fn playerDistComp(pos: [2]f32, lhs: level.Object, rhs: level.Object) bool { const lx = lhs.pos_x - pos[0]; const ly = lhs.pos_y - pos[1]; @@ -148,7 +122,7 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { pub fn renderWorld( self: *@This(), window: RenderWindow, - objects_sprite: Sprite, + objects_image: Image, walls_image: Image, surfaces_image: Image, rendered_surfaces_texture: Texture, @@ -161,7 +135,7 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { self.z_buffer.set(i, std.math.inf(f32)); } - var pixels = [_]Colour{Colour.fromRGBA(0, 0, 0, 0)} ** (PlaneWidth * PlaneHeight); + var pixels = [_]Colour{Colour.Transparent} ** (PlaneWidth * PlaneHeight); // then draw all the walls and populate the z_buffer, while also // rendering the surfaces below the horizon to the pixel array @@ -174,15 +148,20 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { try rendered_surfaces_texture.updateFromPixels(&pixels, null); window.draw(rendered_surfaces_sprite, null); - // use the z_buffer to render sprites - self.renderObjects(window, objects_sprite, map); + // TODO: use the z_buffer to render sprites, reset the + // pixel array as a cheap hack to avoid colour mixing ... + pixels = [_]Colour{Colour.Transparent} ** (PlaneWidth * PlaneHeight); + self.renderObjects(objects_image, map, &pixels); + try rendered_surfaces_texture.updateFromPixels(&pixels, null); + window.draw(rendered_surfaces_sprite, null); + } fn renderObjects( self: @This(), - window: RenderWindow, - objects_sprite: Sprite, + objects_image: Image, map: level.Map, + pixels: []Colour, ) void { std.sort.sort(level.Object, map.objects.items, // Wow, context with an arbitrary type! No macros, just @@ -229,25 +208,40 @@ pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type { // Something is on the screen, let's draw it! const start = std.math.max(0, left); - const end = @floatToInt(i32, std.math.min(left + width, PlaneWidth - 1)); + const end = @floatToInt(usize, std.math.min(left + width, PlaneWidth - 1)); + + const inv_height = 1 / height; var tex_frac: f32 = std.math.clamp((start - left) / width, 0, 1); - var col: i32 = @floatToInt(i32, start); + var col: usize = @floatToInt(usize, start); const tex_frac_step = 1 / width; while (col < end) : ({ col += 1; tex_frac += tex_frac_step; }) { var bottom = std.math.min(top, PlaneHeight); - while (bottom >= 0 and bottom >= top - height) : (bottom -= 1) { - const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + @floatToInt(i32, bottom)); + var pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - bottom, 0))); + var texel_y = (top - bottom) / height; + while (pix_y < PlaneHeight and bottom >= top - height) : ({ + bottom -= 1; + pix_y += 1; + texel_y += inv_height; + }) { + const index = col * @floatToInt(usize, PlaneHeight) + @floatToInt(usize, bottom); if (self.z_buffer.get(index) < scaled_perp_distance) { - bottom += 1; break; + } else { + const tx = @floatToInt(c_uint, tex_frac * constants.TextureDim); + const toff = obj.texture * @floatToInt(c_uint, constants.TextureDim); + const ty = @floatToInt(c_uint, texel_y * constants.TextureDim); + const texel = objects_image.getPixel(.{ .x = toff + tx, .y = ty }); + const pix_index = @floatToInt(usize, PlaneWidth) * pix_y + col; + // TODO: currently i have a cheap hack to + // avoid colour mixing. Is there a better + // way to do this? + pixels[pix_index] = texel; } } - const draw_frac = std.math.clamp((top - bottom) / height, 0, 1); - renderSlice(window, objects_sprite, col, top, height, draw_frac, tex_frac, obj.texture); } } } |
