add movement
This commit is contained in:
		
							parent
							
								
									b3eb24d329
								
							
						
					
					
						commit
						bf4b32236e
					
				
					 3 changed files with 73 additions and 18 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -3,3 +3,5 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Vim
 | 
					# Vim
 | 
				
			||||||
*.swp
 | 
					*.swp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rustenstein.md
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ impl Position {
 | 
				
			||||||
type Degree = f64;
 | 
					type Degree = f64;
 | 
				
			||||||
type Radian = f64;
 | 
					type Radian = f64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct Player {
 | 
					struct Player {
 | 
				
			||||||
   pos: Position,
 | 
					   pos: Position,
 | 
				
			||||||
   angle: Degree,
 | 
					   angle: Degree,
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,14 @@ pub struct Level {
 | 
				
			||||||
    pub tiles: Vec<Tile>,
 | 
					    pub tiles: Vec<Tile>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, PartialEq, Debug)]
 | 
				
			||||||
 | 
					pub enum Movement {
 | 
				
			||||||
 | 
					    Forward,
 | 
				
			||||||
 | 
					    Backward,
 | 
				
			||||||
 | 
					    TurnLeft,
 | 
				
			||||||
 | 
					    TurnRight,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Level {
 | 
					impl Level {
 | 
				
			||||||
    pub fn contains(&self, pos: Position) -> bool {
 | 
					    pub fn contains(&self, pos: Position) -> bool {
 | 
				
			||||||
        0.0 <= pos.x && pos.x <= self.width as f64 && 0.0 <= pos.y && pos.y <= self.height as f64
 | 
					        0.0 <= pos.x && pos.x <= self.width as f64 && 0.0 <= pos.y && pos.y <= self.height as f64
 | 
				
			||||||
| 
						 | 
					@ -51,6 +60,7 @@ pub struct Engine {
 | 
				
			||||||
    horiz_fov: Degree,
 | 
					    horiz_fov: Degree,
 | 
				
			||||||
    player: Player,
 | 
					    player: Player,
 | 
				
			||||||
    level: Level,
 | 
					    level: Level,
 | 
				
			||||||
 | 
					    inputs: Vec<Movement>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Engine {
 | 
					impl Engine {
 | 
				
			||||||
| 
						 | 
					@ -61,22 +71,25 @@ impl Engine {
 | 
				
			||||||
            horiz_fov: 90.,
 | 
					            horiz_fov: 90.,
 | 
				
			||||||
            player: Player {
 | 
					            player: Player {
 | 
				
			||||||
                pos: Position { x: 2., y: 2. },
 | 
					                pos: Position { x: 2., y: 2. },
 | 
				
			||||||
                angle: 0.,
 | 
					                angle: 90.,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            level: Level {
 | 
					            level: Level {
 | 
				
			||||||
                width: 0,
 | 
					                width: 0,
 | 
				
			||||||
                height: 0,
 | 
					                height: 0,
 | 
				
			||||||
                tiles: vec![],
 | 
					                tiles: vec![],
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            inputs: [].to_vec(),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn closest_point(level: &Level, pos: &Position, angle: Radian) -> (Tile, Position) {
 | 
					    fn closest_point(level: &Level, pos: &Position, angle: Radian) -> (Tile, Position) {
 | 
				
			||||||
 | 
					        assert!((0.0..(PI * 2.0)).contains(&angle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let (y_step, x_step) = match angle {
 | 
					        let (y_step, x_step) = match angle {
 | 
				
			||||||
            0.0 => (0.0, std::f64::INFINITY),
 | 
					            x if x == 0.0 => (0.0, std::f64::INFINITY),
 | 
				
			||||||
            90.0 => (std::f64::INFINITY, 0.0),
 | 
					            x if x == PI * 0.5 => (std::f64::INFINITY, 0.0),
 | 
				
			||||||
            180.0 => (0.0, std::f64::NEG_INFINITY),
 | 
					            x if x == PI => (0.0, std::f64::NEG_INFINITY),
 | 
				
			||||||
            270.0 => (std::f64::NEG_INFINITY, 0.0),
 | 
					            x if x == PI * 1.5 => (std::f64::NEG_INFINITY, 0.0),
 | 
				
			||||||
            x if (0.0..(PI * 0.5)).contains(&x) => (angle.tan(), ((PI / 2.0) - angle).tan()),
 | 
					            x if (0.0..(PI * 0.5)).contains(&x) => (angle.tan(), ((PI / 2.0) - angle).tan()),
 | 
				
			||||||
            x if ((PI * 0.5)..PI).contains(&x) => ((PI - x).tan(), -((x - (PI / 2.0)).tan())),
 | 
					            x if ((PI * 0.5)..PI).contains(&x) => ((PI - x).tan(), -((x - (PI / 2.0)).tan())),
 | 
				
			||||||
            x if (PI..(PI * 1.5)).contains(&x) => (-((x - PI).tan()), -(((PI * 1.5) - x).tan())),
 | 
					            x if (PI..(PI * 1.5)).contains(&x) => (-((x - PI).tan()), -(((PI * 1.5) - x).tan())),
 | 
				
			||||||
| 
						 | 
					@ -162,41 +175,66 @@ impl Engine {
 | 
				
			||||||
                  context.transform,
 | 
					                  context.transform,
 | 
				
			||||||
                  graphics);
 | 
					                  graphics);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Walls
 | 
					 | 
				
			||||||
        let left = self.player.angle + (self.horiz_fov / 2.0);
 | 
					        let left = self.player.angle + (self.horiz_fov / 2.0);
 | 
				
			||||||
        let right = self.player.angle - (self.horiz_fov / 2.0);
 | 
					        let right = self.player.angle - (self.horiz_fov / 2.0);
 | 
				
			||||||
        // for every angle (range / w)
 | 
					        let step = self.horiz_fov / self.w;
 | 
				
			||||||
        let step = (left - right) / self.w;
 | 
					 | 
				
			||||||
        let mut ray_angle = left;
 | 
					        let mut ray_angle = left;
 | 
				
			||||||
        let width = self.w as i32;
 | 
					        let width = self.w as i32;
 | 
				
			||||||
        for n in 0..width {
 | 
					        for n in 0..width {
 | 
				
			||||||
            //   cast a ray
 | 
					            let ray_angle = ((left - (n as f64) * step) + 360.0) % 360.0;
 | 
				
			||||||
            let ray_radian = ray_angle.to_radians();
 | 
					            let ray_radian = ray_angle.to_radians();
 | 
				
			||||||
 | 
					            //println!("degree: {} -> radian: {}", ray_angle, ray_radian);
 | 
				
			||||||
            let (tile, pos) = Engine::closest_point(&self.level, &self.player.pos, ray_radian);
 | 
					            let (tile, pos) = Engine::closest_point(&self.level, &self.player.pos, ray_radian);
 | 
				
			||||||
            let distance = self.player.pos.distance(pos);
 | 
					            let distance = self.player.pos.distance(pos);
 | 
				
			||||||
            let player_space_distance = (self.player.pos.x - pos.x).abs() * ray_radian.cos()
 | 
					            let player_space_distance = (self.player.pos.x - pos.x).abs() * self.player.angle.to_radians().cos()
 | 
				
			||||||
                - (self.player.pos.y - pos.y).abs() * ray_radian.sin();
 | 
					                - (self.player.pos.y - pos.y).abs() * self.player.angle.to_radians().sin();
 | 
				
			||||||
            if tile == Tile::Wall {
 | 
					            if tile == Tile::Wall {
 | 
				
			||||||
                println!("ray: {}, wall at {:?}, distance: {}", n, pos, distance);
 | 
					                //println!("ray: {}, wall at {:?}, distance: {}", n, pos, distance);
 | 
				
			||||||
                let wall_height = (self.h / (distance * 3.0)).min(self.h);
 | 
					                let wall_height = (self.h / (distance * 3.0)).min(self.h);
 | 
				
			||||||
                let wall_color = [0.9, 0.2, 0.2, 1.0];
 | 
					                let wall_color = [0.2, 0.2, 0.9, 1.0];
 | 
				
			||||||
                println!("wall height: {}", wall_height);
 | 
					                //println!("wall height: {}", wall_height);
 | 
				
			||||||
                rectangle(wall_color,
 | 
					                rectangle(wall_color,
 | 
				
			||||||
                          [n as f64, (self.h - wall_height) / 2.0, (n + 1) as f64, wall_height],
 | 
					                          [n as f64, (self.h - wall_height) / 2.0, (n + 1) as f64, wall_height],
 | 
				
			||||||
                          context.transform,
 | 
					                          context.transform,
 | 
				
			||||||
                          graphics);
 | 
					                          graphics);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            //   see what wall it hits
 | 
					 | 
				
			||||||
            //   compute wall height
 | 
					 | 
				
			||||||
            //   draw wall portion
 | 
					 | 
				
			||||||
            ray_angle += step;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn load_level(&mut self, level: Level) {
 | 
					    pub fn load_level(&mut self, level: Level) {
 | 
				
			||||||
        self.level = level;
 | 
					        self.level = level;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn add_movement(&mut self, movement: Movement) {
 | 
				
			||||||
 | 
					        self.inputs.push(movement);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn update(&mut self, dt: f64) {
 | 
				
			||||||
 | 
					        for input in &self.inputs {
 | 
				
			||||||
 | 
					            match input {
 | 
				
			||||||
 | 
					                Movement::Forward => {
 | 
				
			||||||
 | 
					                    self.player.pos.x += self.player.angle.to_radians().cos() * dt;
 | 
				
			||||||
 | 
					                    self.player.pos.y += self.player.angle.to_radians().sin() * dt;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Movement::Backward => {
 | 
				
			||||||
 | 
					                    self.player.pos.x -= self.player.angle.to_radians().cos() * dt;
 | 
				
			||||||
 | 
					                    self.player.pos.y -= self.player.angle.to_radians().sin() * dt;
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                Movement::TurnLeft => {
 | 
				
			||||||
 | 
					                    self.player.angle += 90.0 * dt;
 | 
				
			||||||
 | 
					                    self.player.angle = (self.player.angle + 360.0) % 360.0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Movement::TurnRight => {
 | 
				
			||||||
 | 
					                    self.player.angle -= 90.0 * dt;
 | 
				
			||||||
 | 
					                    self.player.angle = (self.player.angle + 360.0) % 360.0;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.inputs.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        println!("player: {:?}", &self.player);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
					@ -29,8 +29,23 @@ fn main() {
 | 
				
			||||||
    engine.load_level(level);
 | 
					    engine.load_level(level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while let Some(event) = window.next() {
 | 
					    while let Some(event) = window.next() {
 | 
				
			||||||
 | 
					        if let Some(Button::Keyboard(key)) = event.press_args() {
 | 
				
			||||||
 | 
					            match key {
 | 
				
			||||||
 | 
					                Key::W => engine.add_movement(engine::Movement::Forward),
 | 
				
			||||||
 | 
					                Key::S => engine.add_movement(engine::Movement::Backward),
 | 
				
			||||||
 | 
					                Key::A => engine.add_movement(engine::Movement::TurnLeft),
 | 
				
			||||||
 | 
					                Key::D => engine.add_movement(engine::Movement::TurnRight),
 | 
				
			||||||
 | 
					                _ => (),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        window.draw_2d(&event, |context, graphics, _device| {
 | 
					        window.draw_2d(&event, |context, graphics, _device| {
 | 
				
			||||||
            engine.render(context, graphics);
 | 
					            engine.render(context, graphics);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some(args) = event.update_args() {
 | 
				
			||||||
 | 
					            engine.update(args.dt);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue