From bf4b32236e7db14396501eecca4290e16a95a3e4 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Tue, 31 Mar 2020 15:14:12 +0200 Subject: [PATCH] add movement --- .gitignore | 2 ++ src/engine.rs | 74 ++++++++++++++++++++++++++++++++++++++------------- src/main.rs | 15 +++++++++++ 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index f47b7ab..7c86dde 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ # Vim *.swp + +rustenstein.md diff --git a/src/engine.rs b/src/engine.rs index b3a03c4..c606037 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -22,6 +22,7 @@ impl Position { type Degree = f64; type Radian = f64; +#[derive(Debug)] struct Player { pos: Position, angle: Degree, @@ -39,6 +40,14 @@ pub struct Level { pub tiles: Vec, } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Movement { + Forward, + Backward, + TurnLeft, + TurnRight, +} + impl Level { 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 @@ -51,6 +60,7 @@ pub struct Engine { horiz_fov: Degree, player: Player, level: Level, + inputs: Vec, } impl Engine { @@ -61,22 +71,25 @@ impl Engine { horiz_fov: 90., player: Player { pos: Position { x: 2., y: 2. }, - angle: 0., + angle: 90., }, level: Level { width: 0, height: 0, tiles: vec![], }, + inputs: [].to_vec(), } } 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 { - 0.0 => (0.0, std::f64::INFINITY), - 90.0 => (std::f64::INFINITY, 0.0), - 180.0 => (0.0, std::f64::NEG_INFINITY), - 270.0 => (std::f64::NEG_INFINITY, 0.0), + x if x == 0.0 => (0.0, std::f64::INFINITY), + x if x == PI * 0.5 => (std::f64::INFINITY, 0.0), + x if x == PI => (0.0, std::f64::NEG_INFINITY), + 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 ((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())), @@ -162,41 +175,66 @@ impl Engine { context.transform, graphics); - // Walls let left = 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 = (left - right) / self.w; + let step = self.horiz_fov / self.w; let mut ray_angle = left; let width = self.w as i32; 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(); + //println!("degree: {} -> radian: {}", ray_angle, ray_radian); let (tile, pos) = Engine::closest_point(&self.level, &self.player.pos, ray_radian); let distance = self.player.pos.distance(pos); - let player_space_distance = (self.player.pos.x - pos.x).abs() * ray_radian.cos() - - (self.player.pos.y - pos.y).abs() * ray_radian.sin(); + let player_space_distance = (self.player.pos.x - pos.x).abs() * self.player.angle.to_radians().cos() + - (self.player.pos.y - pos.y).abs() * self.player.angle.to_radians().sin(); 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_color = [0.9, 0.2, 0.2, 1.0]; - println!("wall height: {}", wall_height); + let wall_color = [0.2, 0.2, 0.9, 1.0]; + //println!("wall height: {}", wall_height); rectangle(wall_color, [n as f64, (self.h - wall_height) / 2.0, (n + 1) as f64, wall_height], context.transform, graphics); }; - // see what wall it hits - // compute wall height - // draw wall portion - ray_angle += step; } } pub fn load_level(&mut 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)] diff --git a/src/main.rs b/src/main.rs index f93e77f..a2b00fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,8 +29,23 @@ fn main() { engine.load_level(level); 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| { engine.render(context, graphics); }); + + if let Some(args) = event.update_args() { + engine.update(args.dt); + } + } }