Bladeren bron

Fixed rendering and collision bugs. Updated colour scheme

Gary Munnelly 2 jaren geleden
bovenliggende
commit
d43073b56d
5 gewijzigde bestanden met toevoegingen van 64 en 40 verwijderingen
  1. 4 0
      src/consts.rs
  2. 0 7
      src/fp.rs
  3. 39 5
      src/lib.rs
  4. 16 12
      src/raycast.rs
  5. 5 16
      src/trig.rs

+ 4 - 0
src/consts.rs

@@ -1,5 +1,6 @@
 use crate::fp::ToFixedPoint;
 
+pub const PROJECTION_PLANE_HEIGHT: i32 = 200;
 pub const PROJECTION_PLANE_WIDTH: i32 = 320;
 pub const TILE_SIZE: i32 = 64;
 pub const FP_TILE_SIZE: i32 = TILE_SIZE << 16;
@@ -7,3 +8,6 @@ pub const FP_TILE_SIZE: i32 = TILE_SIZE << 16;
 pub const WALL_HEIGHT_SCALE_FACTOR: i32 = 18000;
 pub const WALL_HEIGHT_MIN: i32 = 8;
 pub const WALL_HEIGHT_MAX: i32 = 640;
+
+pub const MAX_RAY_LENGTH: i32 = 2048;
+pub const FP_MAX_RAY_LENGTH: i32 = MAX_RAY_LENGTH << 16;

+ 0 - 7
src/fp.rs

@@ -11,13 +11,6 @@ pub trait FromFixedPoint {
     fn to_i32(&self) -> i32;
 }
 
-pub trait FixedPointMath {
-	fn fp_add(&self, b: i32) -> i32;
-	fn fp_sub(&self, b: i32) -> i32;
-	fn fp_mul(&self, b: i32) -> i32;
-	fn fp_div(&self, b: i32) -> i32;
-}
-
 impl ToFixedPoint for f64 {
     fn to_fp(&self) -> i32 {
         (*self * FP_MULT) as i32

+ 39 - 5
src/lib.rs

@@ -34,7 +34,7 @@ pub struct Cluiche {
 impl Cluiche {
 	pub fn new() -> Cluiche {
 		let world = raycast::World::new(13, 6, "WHHHHWHWHHHHWVOOOOVOVOOOOVVOOOOVOVOOOOVVOOOOVOOOOOOVVOOOOOOVOOOOVWHHHHWHWHHHWW").unwrap();
-		let player = raycast::Player::new(160, 160, 0, 5, 5);
+		let player = raycast::Player::new(160, 160, 0, 5, 10);
 		Cluiche { world, player }
 	}
 
@@ -238,6 +238,9 @@ impl Cluiche {
 		}
 
 		self.player.pos(x1, y1);
+
+		log!("pos=({}, {}) a={}", self.player.x, self.player.y, self.player.rotation);
+
 		hit_result
 	}
 
@@ -259,10 +262,12 @@ impl Cluiche {
 
 	pub fn player_turn_left(&mut self) {
 		self.player.rotation(self.player.rotation - self.player.rotate_speed);
+		log!("pos=({}, {}) a={}", self.player.x, self.player.y, self.player.rotation);
 	}
 
 	pub fn player_turn_right(&mut self) {
 		self.player.rotation(self.player.rotation + self.player.rotate_speed);
+		log!("pos=({}, {}) a={}", self.player.x, self.player.y, self.player.rotation);
 	}
 
 	fn draw_wall_column(&self, buf: &mut[u8], column: i32, dist: i32) {
@@ -280,15 +285,43 @@ impl Cluiche {
 		for y in y_min..=y_max {
 			let idx: usize = 4 * (column + y * consts::PROJECTION_PLANE_WIDTH) as usize;
 			buf[idx + 0] = colour as u8;
-			buf[idx + 1] = 0x00;
-			buf[idx + 2] = 0x00;
+			buf[idx + 1] = colour as u8;
+			buf[idx + 2] = colour as u8;
 			buf[idx + 3] = 0xFF; // alpha channel
 		}
 	}
 
+	fn draw_background(&self, buf: &mut[u8]) {
+		let mut c = 255;
+
+		for y in 0..consts::PROJECTION_PLANE_HEIGHT / 2 {
+			for x in 0..consts::PROJECTION_PLANE_WIDTH {
+				let idx: usize = 4 * (x + y * consts::PROJECTION_PLANE_WIDTH) as usize;
+				buf[idx + 0] = c;
+				buf[idx + 1] = 0x7D;
+				buf[idx + 2] = 0xE1;
+				buf[idx + 3] = 0xFF; // alpha channel				
+			}
+
+			c -= 1;
+		}
+
+		c = 22;
+		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] = c;
+				buf[idx + 1] = 20;
+				buf[idx + 2] = 20;
+				buf[idx + 3] = 0xFF; // alpha channel
+			}
+
+			c += 1;
+		}
+	}
+
 	pub fn render(&mut self, buf: &mut[u8]) {
-		// draw a grey background that will represent the ceiling and floor
-		for x in &mut *buf { *x = 128; }
+		self.draw_background(buf);
 
 		// theta is the direction player is facing
 		// need to start out sweep 30 degrees to the left
@@ -302,6 +335,7 @@ impl Cluiche {
 		let origin_x = self.player.x.to_fp();
 		let origin_y = self.player.y.to_fp();
 
+
 		// sweep of the rays will be through 60 degrees
 		for sweep in 0..trig::ANGLE_60 {
 			let dist = self.world.find_closest_intersect(origin_x, origin_y, angle);

+ 16 - 12
src/raycast.rs

@@ -109,11 +109,11 @@ impl World {
 
 			let hi = ((origin_y.to_i32() / consts::TILE_SIZE) * consts::TILE_SIZE).to_fp();
 			x = fp::add(origin_x, fp::mul(fp::sub(hi, origin_y), trig::itan(direction)));
-			y = fp::sub(hi, consts::FP_TILE_SIZE);
+			y = hi; // fp::sub(hi, 1.to_fp());
 		}
 
 		if direction == trig::ANGLE_0 || direction == trig::ANGLE_180 {
-			return trig::FP_MAX_RAY_LENGTH;
+			return consts::FP_MAX_RAY_LENGTH;
 		}
 
 		// Cast x axis intersect rays, build up xSlice
@@ -127,7 +127,7 @@ impl World {
 			y = fp::add(y, step_y);
 		}
 
-		trig::FP_MAX_RAY_LENGTH
+		consts::FP_MAX_RAY_LENGTH
 	}
 
 	fn find_vertical_intersect(&self, origin_x: i32, origin_y: i32, direction: i32) -> i32 {
@@ -150,17 +150,18 @@ impl World {
 			step_x = -consts::FP_TILE_SIZE;
 			step_y = trig::ystep(direction);
 			
-			x = fp::sub(vi, consts::FP_TILE_SIZE);
+			x = vi; //fp::sub(vi, 1.to_fp());
 			y = fp::add(origin_y, fp::mul(fp::sub(vi, origin_x), trig::tan(direction)));
 		};
 
 		if direction == trig::ANGLE_90 || direction == trig::ANGLE_270 {
-			return trig::FP_MAX_RAY_LENGTH;
+			return consts::FP_MAX_RAY_LENGTH;
 		}
 
 		// Cast y axis intersect rays, build up ySlice
 		while self.is_within_bounds(fp::div(x, consts::FP_TILE_SIZE).to_i32(), fp::div(y, consts::FP_TILE_SIZE).to_i32()) {
 			if self.is_x_wall(fp::div(x, consts::FP_TILE_SIZE).to_i32(), fp::div(y, consts::FP_TILE_SIZE).to_i32()) {
+				println!("V Intersect ({} {})", x.to_i32(), y.to_i32());
 				return fp::mul(fp::sub(x, origin_x), trig::icos(direction)).abs();				
 			}
 
@@ -168,7 +169,7 @@ impl World {
 			y = fp::add(y, step_y);
 		}
 
-		trig::FP_MAX_RAY_LENGTH
+		consts::FP_MAX_RAY_LENGTH
 	}
 
 	pub fn find_closest_intersect(&self, origin_x: i32, origin_y: i32, direction: i32) -> i32 {
@@ -211,21 +212,24 @@ mod test {
 		let world_str = "WHWVOVWHW";
 		let world = World::new(width, height, world_str).unwrap();
 
-		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_0).to_i32(),   trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_0).to_i32(),   consts::MAX_RAY_LENGTH);
 		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_90).to_i32(),  64);
-		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_180).to_i32(), trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_180).to_i32(), consts::MAX_RAY_LENGTH);
 		assert_eq!(world.find_horizontal_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_270).to_i32(), 64);
 		
 		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_0).to_i32(),   64);
-		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_90).to_i32(),  trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_90).to_i32(),  consts::MAX_RAY_LENGTH);
 		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_180).to_i32(), 64);
-		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_270).to_i32(), trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_vertical_intersect(64.to_fp(), 64.to_fp(), trig::ANGLE_270).to_i32(), consts::MAX_RAY_LENGTH);
 
 		let world = World::new(7, 7, "WHHHHHWVOOOOOVVOOOOOVVOOOOOVVOOOOOVVOOOOOVWHHHHHW").unwrap();
 		assert_eq!(world.find_horizontal_intersect(76.to_fp(), 76.to_fp(), 295).to_i32(), 374);
-		assert_eq!(world.find_vertical_intersect(76.to_fp(), 76.to_fp(), 295).to_i32(), trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_vertical_intersect(76.to_fp(), 76.to_fp(), 295).to_i32(), consts::MAX_RAY_LENGTH);
 
 		assert_eq!(world.find_horizontal_intersect(160.to_fp(), 160.to_fp(), 1730).to_i32(), 274);
-		assert_eq!(world.find_vertical_intersect(160.to_fp(), 160.to_fp(), 1730).to_i32(), trig::MAX_RAY_LENGTH);
+		assert_eq!(world.find_vertical_intersect(160.to_fp(), 160.to_fp(), 1730).to_i32(), consts::MAX_RAY_LENGTH);
+
+		let world = World::new(13, 6, "WHHHHWHWHHHHWVOOOOVOVOOOOVVOOOOVOVOOOOVVOOOOVOOOOOOVVOOOOOOVOOOOVWHHHHWHWHHHWW").unwrap();
+		assert_eq!(world.find_vertical_intersect(698.to_fp(), 145.to_fp(), 820).to_i32(), 278);
 	}
 }

+ 5 - 16
src/trig.rs

@@ -1,30 +1,19 @@
-use crate::consts::PROJECTION_PLANE_WIDTH;
-use crate::fp::ToFixedPoint;
+use crate::consts::{ PROJECTION_PLANE_WIDTH, MAX_RAY_LENGTH };
 use core::f64::consts::PI;
 
 include!(concat!(env!("OUT_DIR"), "/lookup.rs"));
 
-pub const ANGLE_0:   i32 = 0;
 pub const ANGLE_60:  i32 = PROJECTION_PLANE_WIDTH;
+
+pub const ANGLE_0:   i32 = 0;
+pub const ANGLE_5:   i32 = ANGLE_60 / 12;
+pub const ANGLE_10:  i32 = ANGLE_60 / 6;
 pub const ANGLE_30:  i32 = ANGLE_60 / 2;
 pub const ANGLE_90:  i32 = ANGLE_30 * 3;
 pub const ANGLE_180: i32 = ANGLE_60 * 3;
 pub const ANGLE_270: i32 = ANGLE_90 * 3;
 pub const ANGLE_360: i32 = ANGLE_60 * 6;
 
-pub const MAX_RAY_LENGTH: i32 = 2048;
-pub const FP_MAX_RAY_LENGTH: i32 = MAX_RAY_LENGTH << 16;
-
-fn clamp(x: i32, min: i32, max: i32) -> i32 {
-	if x < min {
-		min
-	} else if x > max {
-		max
-	} else {
-		x
-	}
-}
-
 pub fn radian(angle: i32) -> f64 {
 	angle as f64 * PI / ANGLE_180 as f64
 }