|
@@ -352,6 +352,14 @@ impl Cluiche {
|
|
|
self.player.rotation(self.player.rotation + self.player.rotate_speed);
|
|
self.player.rotation(self.player.rotation + self.player.rotate_speed);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ pub fn player_look_up(&mut self) {
|
|
|
|
|
+ self.world.move_horizon(5);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn player_look_down(&mut self) {
|
|
|
|
|
+ self.world.move_horizon(-5);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
fn draw_wall_column(&self, buf: &mut[u8], origin_x: i32, origin_y: i32, direction: i32, column: i32, parameters: &mut Vec<ColumnRenderParameters>) {
|
|
fn draw_wall_column(&self, buf: &mut[u8], origin_x: i32, origin_y: i32, direction: i32, column: i32, parameters: &mut Vec<ColumnRenderParameters>) {
|
|
|
let y_min = parameters[0].y_min;
|
|
let y_min = parameters[0].y_min;
|
|
|
let y_max = parameters[0].y_max;
|
|
let y_max = parameters[0].y_max;
|
|
@@ -372,21 +380,49 @@ impl Cluiche {
|
|
|
(r, g, b, a) = blend_colours(r, g, b, a, slice.texture[tex_y + 0], slice.texture[tex_y + 1], slice.texture[tex_y + 2], slice.texture[tex_y + 3]);
|
|
(r, g, b, a) = blend_colours(r, g, b, a, slice.texture[tex_y + 0], slice.texture[tex_y + 1], slice.texture[tex_y + 2], slice.texture[tex_y + 3]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if a < 255 && y >= consts::PROJECTION_PLANE_HORIZON {
|
|
|
|
|
- let floor = self.world.find_floor_intersection(origin_x, origin_y, direction, y, column);
|
|
|
|
|
|
|
+ if a < 255 {
|
|
|
|
|
+ if y >= *self.world.horizon() {
|
|
|
|
|
+ let floor = self.world.find_floor_intersection(origin_x, origin_y, direction, y, column);
|
|
|
|
|
|
|
|
- if let raycast::TextureCode::Floor(code, x, y) = floor {
|
|
|
|
|
- let texture = self.textures.get(code, x, false);
|
|
|
|
|
- let tex_y = (y * 4) as usize;
|
|
|
|
|
- (r, g, b, a) = blend_colours(r, g, b, a, texture[tex_y + 0], texture[tex_y + 1], texture[tex_y + 2], texture[tex_y + 3]);
|
|
|
|
|
|
|
+ if let raycast::TextureCode::Floor(code, x, y) = floor {
|
|
|
|
|
+ let texture = self.textures.get(code, x, false);
|
|
|
|
|
+ let tex_y = (y * 4) as usize;
|
|
|
|
|
+ (r, g, b, a) = blend_colours(r, g, b, a, texture[tex_y + 0], texture[tex_y + 1], texture[tex_y + 2], texture[tex_y + 3]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ (r, g, b, a) = blend_colours(r, g, b, a, 0x70, 0x70, 0x70, 0xFF);
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- (r, g, b, a) = blend_colours(r, g, b, a, 0x70, 0x70, 0x70, 0xFF);
|
|
|
|
|
|
|
+ let ceiling = self.world.find_ceiling_intersection(origin_x, origin_y, direction, y, column);
|
|
|
|
|
+
|
|
|
|
|
+ if let raycast::TextureCode::Ceiling(code, x, y) = ceiling {
|
|
|
|
|
+ let texture = self.textures.get(code, x, false);
|
|
|
|
|
+ let tex_y = (y * 4) as usize;
|
|
|
|
|
+ (r, g, b, a) = blend_colours(r, g, b, a, texture[tex_y + 0], texture[tex_y + 1], texture[tex_y + 2], texture[tex_y + 3]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ (r, g, b, a) = blend_colours(r, g, b, a, 0x70, 0x70, 0x70, 0xFF);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
(buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = blend_colours(r, g, b, a, buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]);
|
|
(buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = blend_colours(r, g, b, a, buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // texture the ceiling
|
|
|
|
|
+ for y in 0..(y_min) {
|
|
|
|
|
+ let ceiling = self.world.find_ceiling_intersection(origin_x, origin_y, direction, y, column);
|
|
|
|
|
+ let idx: usize = 4 * (column + y * consts::PROJECTION_PLANE_WIDTH) as usize;
|
|
|
|
|
+
|
|
|
|
|
+ if let raycast::TextureCode::Ceiling(code, x, y) = ceiling {
|
|
|
|
|
+ let texture = self.textures.get(code, x, false);
|
|
|
|
|
+ let tex_y = (y * 4) as usize;
|
|
|
|
|
+
|
|
|
|
|
+ (buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = (texture[tex_y + 0], texture[tex_y + 1], texture[tex_y + 2], texture[tex_y + 3]);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ (buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = (0x70, 0x70, 0x70, 0xFF);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // texture the floor
|
|
|
for y in (y_max + 1)..consts::PROJECTION_PLANE_HEIGHT {
|
|
for y in (y_max + 1)..consts::PROJECTION_PLANE_HEIGHT {
|
|
|
let floor = self.world.find_floor_intersection(origin_x, origin_y, direction, y, column);
|
|
let floor = self.world.find_floor_intersection(origin_x, origin_y, direction, y, column);
|
|
|
let idx: usize = 4 * (column + y * consts::PROJECTION_PLANE_WIDTH) as usize;
|
|
let idx: usize = 4 * (column + y * consts::PROJECTION_PLANE_WIDTH) as usize;
|
|
@@ -395,15 +431,9 @@ impl Cluiche {
|
|
|
let texture = self.textures.get(code, x, false);
|
|
let texture = self.textures.get(code, x, false);
|
|
|
let tex_y = (y * 4) as usize;
|
|
let tex_y = (y * 4) as usize;
|
|
|
|
|
|
|
|
- buf[idx + 0] = texture[tex_y + 0];
|
|
|
|
|
- buf[idx + 1] = texture[tex_y + 1];
|
|
|
|
|
- buf[idx + 2] = texture[tex_y + 2];
|
|
|
|
|
- buf[idx + 3] = texture[tex_y + 3];
|
|
|
|
|
|
|
+ (buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = (texture[tex_y + 0], texture[tex_y + 1], texture[tex_y + 2], texture[tex_y + 3]);
|
|
|
} else {
|
|
} else {
|
|
|
- buf[idx + 0] = 0x70;
|
|
|
|
|
- buf[idx + 1] = 0x70;
|
|
|
|
|
- buf[idx + 2] = 0x70;
|
|
|
|
|
- buf[idx + 3] = 0xFF;
|
|
|
|
|
|
|
+ (buf[idx + 0], buf[idx + 1], buf[idx + 2], buf[idx + 3]) = (0x70, 0x70, 0x70, 0xFF);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -420,19 +450,19 @@ impl Cluiche {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // for y in consts::PROJECTION_PLANE_HEIGHT / 2..consts::PROJECTION_PLANE_HEIGHT {
|
|
|
|
|
- // for x in 0..consts::PROJECTION_PLANE_WIDTH {
|
|
|
|
|
- // let idx: usize = 4 * (x + y * consts::PROJECTION_PLANE_WIDTH) as usize;
|
|
|
|
|
- // buf[idx + 0] = 0x70;
|
|
|
|
|
- // buf[idx + 1] = 0x70;
|
|
|
|
|
- // buf[idx + 2] = 0x70;
|
|
|
|
|
- // buf[idx + 3] = 0xFF; // alpha channel
|
|
|
|
|
- // }
|
|
|
|
|
- // }
|
|
|
|
|
|
|
+ for y in consts::PROJECTION_PLANE_HEIGHT / 2..consts::PROJECTION_PLANE_HEIGHT {
|
|
|
|
|
+ for x in 0..consts::PROJECTION_PLANE_WIDTH {
|
|
|
|
|
+ let idx: usize = 4 * (x + y * consts::PROJECTION_PLANE_WIDTH) as usize;
|
|
|
|
|
+ buf[idx + 0] = 0x70;
|
|
|
|
|
+ buf[idx + 1] = 0x70;
|
|
|
|
|
+ buf[idx + 2] = 0x70;
|
|
|
|
|
+ buf[idx + 3] = 0xFF; // alpha channel
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn render(&mut self, buf: &mut[u8]) {
|
|
pub fn render(&mut self, buf: &mut[u8]) {
|
|
|
- self.draw_background(buf);
|
|
|
|
|
|
|
+ // self.draw_background(buf);
|
|
|
|
|
|
|
|
// theta is the direction player is facing
|
|
// theta is the direction player is facing
|
|
|
// need to start out sweep 30 degrees to the left
|
|
// need to start out sweep 30 degrees to the left
|
|
@@ -458,13 +488,13 @@ impl Cluiche {
|
|
|
for slice in slices {
|
|
for slice in slices {
|
|
|
let dist = fp::div(slice.distance, trig::fisheye_correction(sweep)).to_i32();
|
|
let dist = fp::div(slice.distance, trig::fisheye_correction(sweep)).to_i32();
|
|
|
let wall_height: i32 = trig::wall_height(dist);
|
|
let wall_height: i32 = trig::wall_height(dist);
|
|
|
- let y_min = std::cmp::max(0, (200 - wall_height) / 2);
|
|
|
|
|
- let y_max = std::cmp::min(200 - 1, y_min + wall_height);
|
|
|
|
|
|
|
+ let y_min = std::cmp::max(0, self.world.horizon() - wall_height / 2);
|
|
|
|
|
+ let y_max = std::cmp::min(consts::PROJECTION_PLANE_HEIGHT - 1, self.world.horizon() + wall_height / 2);
|
|
|
let step: f64 = consts::TEXTURE_HEIGHT as f64 / wall_height as f64;
|
|
let step: f64 = consts::TEXTURE_HEIGHT as f64 / wall_height as f64;
|
|
|
|
|
|
|
|
if let raycast::TextureCode::Wall(code, texture_column, flipped) = slice.texture {
|
|
if let raycast::TextureCode::Wall(code, texture_column, flipped) = slice.texture {
|
|
|
let texture = self.textures.get(code, texture_column, flipped);
|
|
let texture = self.textures.get(code, texture_column, flipped);
|
|
|
- let tex_pos: f64 = (y_min as f64 - consts::PROJECTION_PLANE_HEIGHT as f64 / 2.0 + wall_height as f64 / 2.0) * step;
|
|
|
|
|
|
|
+ let tex_pos: f64 = (y_min as f64 - *self.world.horizon() as f64 + wall_height as f64 / 2.0) * step;
|
|
|
parameters.push(ColumnRenderParameters::new(texture, step, wall_height, tex_pos, y_min, y_max))
|
|
parameters.push(ColumnRenderParameters::new(texture, step, wall_height, tex_pos, y_min, y_max))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|