add movement
This commit is contained in:
parent
b3eb24d329
commit
bf4b32236e
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…
Reference in a new issue