change window dep from piston to minifb

master
Fabien Freling 2021-11-04 14:03:12 +01:00
parent 4620f647ad
commit 3844c0fe80
5 changed files with 728 additions and 1079 deletions

1569
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,14 @@
[package] [package]
name = "rustenstein" name = "rustenstein"
version = "0.1.0" version = "0.1.0"
edition = "2021"
authors = ["Fabien Freling <public@ffreling.com>"] authors = ["Fabien Freling <public@ffreling.com>"]
[dependencies] [dependencies]
piston_window = "0.107.0" minifb = "0.19.3"
# From https://fasterthanli.me/articles/my-ideal-rust-workflow#advice-start
[profile.release]
debug = 1
incremental = true
lto = "off"

3
rust-toolchain.toml Normal file
View File

@ -0,0 +1,3 @@
[toolchain]
channel = "1.56.1"
components = [ "rustfmt", "clippy" ]

View File

@ -1,5 +1,5 @@
extern crate piston_window; // extern crate piston_window;
use piston_window::*; // use piston_window::*;
use std::f64::consts::*; use std::f64::consts::*;
@ -24,12 +24,12 @@ type Radian = f64;
#[derive(Debug)] #[derive(Debug)]
struct Player { struct Player {
pos: Position, pos: Position,
angle: Degree, angle: Degree,
} }
impl Player { impl Player {
pub fn player_space_distance(&self, other: Position) ->f64 { pub fn player_space_distance(&self, other: Position) -> f64 {
let rad = self.angle.to_radians(); let rad = self.angle.to_radians();
let dx = other.x - self.pos.x; let dx = other.x - self.pos.x;
let dy = other.y - self.pos.y; let dy = other.y - self.pos.y;
@ -42,7 +42,6 @@ impl Player {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum Tile { pub enum Tile {
Empty, Empty,
@ -159,10 +158,10 @@ pub struct Engine {
} }
impl Engine { impl Engine {
pub fn new(size: Size) -> Engine { pub fn new(width: usize, height: usize) -> Engine {
Engine { Engine {
w: size.width as f64, w: width as f64,
h: size.height as f64, h: height as f64,
horiz_fov: 90., horiz_fov: 90.,
player: Player { player: Player {
pos: Position { x: 1.5, y: 2. }, pos: Position { x: 1.5, y: 2. },
@ -177,22 +176,26 @@ impl Engine {
} }
} }
pub fn render(&mut self, context: Context, graphics: &mut G2d) { pub fn render(&mut self, buffer: &mut Vec<u32>) {
clear([1.0; 4], graphics); // clear([1.0; 4], graphics);
// Ceiling // // Ceiling
let ceiling_color = [0.3, 0.3, 0.3, 1.0]; // let ceiling_color = [0.3, 0.3, 0.3, 1.0];
rectangle(ceiling_color, // rectangle(
[0.0, 0.0, self.w, self.h / 2.0], // ceiling_color,
context.transform, // [0.0, 0.0, self.w, self.h / 2.0],
graphics); // context.transform,
// graphics,
// );
// Floor // // Floor
let floor_color = [0.5, 0.5, 0.5, 1.0]; // let floor_color = [0.5, 0.5, 0.5, 1.0];
rectangle(floor_color, // rectangle(
[0.0, self.h / 2.0, self.w, self.h / 2.0], // floor_color,
context.transform, // [0.0, self.h / 2.0, self.w, self.h / 2.0],
graphics); // context.transform,
// graphics,
// );
let left = self.player.angle + (self.horiz_fov / 2.0); let left = self.player.angle + (self.horiz_fov / 2.0);
let step = self.horiz_fov / self.w; let step = self.horiz_fov / self.w;
@ -211,11 +214,16 @@ impl Engine {
p if (p.x.trunc() + p.y.trunc()) % 4.0 == 3.0 => [0.7, 0.3, 0.9, 1.0], p if (p.x.trunc() + p.y.trunc()) % 4.0 == 3.0 => [0.7, 0.3, 0.9, 1.0],
_ => [1.0, 0.0, 0.0, 1.0], _ => [1.0, 0.0, 0.0, 1.0],
}; };
println!("ray: {}, angle: {}, wall at {:?}, distance: {}", n, ray_angle, pos, distance); println!(
rectangle(wall_color, "ray: {}, angle: {}, wall at {:?}, distance: {}",
[n as f64, (self.h - wall_height) / 2.0, 1.0, wall_height], n, ray_angle, pos, distance
context.transform, );
graphics); // rectangle(
// wall_color,
// [n as f64, (self.h - wall_height) / 2.0, 1.0, wall_height],
// context.transform,
// graphics,
// );
}; };
} }
@ -241,7 +249,7 @@ impl Engine {
Movement::Backward => { Movement::Backward => {
self.player.pos.x -= self.player.angle.to_radians().cos() * dt; self.player.pos.x -= self.player.angle.to_radians().cos() * dt;
self.player.pos.y -= self.player.angle.to_radians().sin() * dt; self.player.pos.y -= self.player.angle.to_radians().sin() * dt;
}, }
Movement::TurnLeft => { Movement::TurnLeft => {
self.player.angle += 90.0 * dt; self.player.angle += 90.0 * dt;
self.player.angle = (self.player.angle + 360.0) % 360.0; self.player.angle = (self.player.angle + 360.0) % 360.0;
@ -251,8 +259,14 @@ impl Engine {
self.player.angle = (self.player.angle + 360.0) % 360.0; self.player.angle = (self.player.angle + 360.0) % 360.0;
} }
} }
if !self.level.contains(self.player.pos) || self.level.tile_at(self.player.pos) == Tile::Wall { if !self.level.contains(self.player.pos)
println!("Invalid position {:?}, tile = {:?}", self.player.pos, self.level.tile_at(self.player.pos)); || self.level.tile_at(self.player.pos) == Tile::Wall
{
println!(
"Invalid position {:?}, tile = {:?}",
self.player.pos,
self.level.tile_at(self.player.pos)
);
self.player.pos = previous; self.player.pos = previous;
} }
} }
@ -278,31 +292,71 @@ mod tests {
angle: 0., angle: 0.,
}; };
fcmp(player.player_space_distance(super::Position { x: 4., y: 1. }), 2.); fcmp(
fcmp(player.player_space_distance(super::Position { x: 4., y: 2. }), 2.); player.player_space_distance(super::Position { x: 4., y: 1. }),
fcmp(player.player_space_distance(super::Position { x: 4., y: 3. }), 2.); 2.,
);
fcmp(
player.player_space_distance(super::Position { x: 4., y: 2. }),
2.,
);
fcmp(
player.player_space_distance(super::Position { x: 4., y: 3. }),
2.,
);
player.angle = 90.; player.angle = 90.;
fcmp(player.player_space_distance(super::Position { x: 1., y: 4. }), 2.); fcmp(
fcmp(player.player_space_distance(super::Position { x: 2., y: 4. }), 2.); player.player_space_distance(super::Position { x: 1., y: 4. }),
fcmp(player.player_space_distance(super::Position { x: 3., y: 4. }), 2.); 2.,
);
fcmp(
player.player_space_distance(super::Position { x: 2., y: 4. }),
2.,
);
fcmp(
player.player_space_distance(super::Position { x: 3., y: 4. }),
2.,
);
player.angle = 135.; player.angle = 135.;
fcmp(player.player_space_distance(super::Position { x: 0., y: 2. }), 2.); fcmp(
player.player_space_distance(super::Position { x: 0., y: 2. }),
2.,
);
player.angle = 180.; player.angle = 180.;
fcmp(player.player_space_distance(super::Position { x: 0., y: 1. }), 2.); fcmp(
fcmp(player.player_space_distance(super::Position { x: 0., y: 2. }), 2.); player.player_space_distance(super::Position { x: 0., y: 1. }),
fcmp(player.player_space_distance(super::Position { x: 0., y: 3. }), 2.); 2.,
);
fcmp(
player.player_space_distance(super::Position { x: 0., y: 2. }),
2.,
);
fcmp(
player.player_space_distance(super::Position { x: 0., y: 3. }),
2.,
);
player.angle = 270.; player.angle = 270.;
fcmp(player.player_space_distance(super::Position { x: 1., y: 0. }), 2.); fcmp(
fcmp(player.player_space_distance(super::Position { x: 2., y: 0. }), 2.); player.player_space_distance(super::Position { x: 1., y: 0. }),
fcmp(player.player_space_distance(super::Position { x: 3., y: 0. }), 2.); 2.,
);
fcmp(
player.player_space_distance(super::Position { x: 2., y: 0. }),
2.,
);
fcmp(
player.player_space_distance(super::Position { x: 3., y: 0. }),
2.,
);
} }
#[test] #[test]
fn tile_at() { fn tile_at() {
#[rustfmt::skip]
let tiles = vec![ let tiles = vec![
Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall,
Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall, Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall,
@ -313,9 +367,12 @@ mod tests {
let level = Level { let level = Level {
width: 5, width: 5,
height: 5, height: 5,
tiles tiles,
}; };
assert_eq!(level.tile_at(super::Position { x: 2.0, y: 2.0 }), Tile::Empty); assert_eq!(
level.tile_at(super::Position { x: 2.0, y: 2.0 }),
Tile::Empty
);
} }
#[test] #[test]
@ -336,6 +393,7 @@ mod tests {
#[test] #[test]
fn closest_point() { fn closest_point() {
#[rustfmt::skip]
let tiles = vec![ let tiles = vec![
Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall,
Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall, Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall,
@ -346,7 +404,7 @@ mod tests {
let level = Level { let level = Level {
width: 5, width: 5,
height: 5, height: 5,
tiles tiles,
}; };
let position = super::Position { x: 2.5, y: 2.0 }; let position = super::Position { x: 2.5, y: 2.0 };
@ -377,7 +435,8 @@ mod tests {
let right_ray_angle = ((-(n as f64) * step) + 360.0) % 360.0; let right_ray_angle = ((-(n as f64) * step) + 360.0) % 360.0;
let right_ray_radian = right_ray_angle.to_radians(); let right_ray_radian = right_ray_angle.to_radians();
let (_right_tile, right_pos) = super::closest_point(&level, &position, right_ray_radian); let (_right_tile, right_pos) =
super::closest_point(&level, &position, right_ray_radian);
println!("left: {:?}, angle: {}", left_pos, left_ray_angle); println!("left: {:?}, angle: {}", left_pos, left_ray_angle);
println!("right: {:?}, angle: {}", right_pos, right_ray_angle); println!("right: {:?}, angle: {}", right_pos, right_ray_angle);

View File

@ -1,19 +1,30 @@
extern crate piston_window; // extern crate piston_window;
use piston_window::*; // use piston_window::*;
extern crate minifb;
use minifb::{Key, Window, WindowOptions};
mod engine; mod engine;
use engine::Tile; use engine::Tile;
const WIDTH: usize = 320;
const HEIGHT: usize = 240;
fn main() { fn main() {
let mut window: PistonWindow = let mut buffer: Vec<u32> = vec![0; WIDTH * HEIGHT];
WindowSettings::new("Rustenstein", [320, 240])
.exit_on_esc(true)
.resizable(false)
.build()
.unwrap_or_else(|e| { panic!("Failed to build PistonWindow: {}", e) });
let mut engine = engine::Engine::new(window.size()); let mut window = Window::new("Rustenstein", WIDTH, HEIGHT, WindowOptions::default())
.unwrap_or_else(|e| {
panic!("{}", e);
});
// Limit to max ~60 fps update rate
window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
let (width, height) = window.get_size();
let mut engine = engine::Engine::new(width, height);
#[rustfmt::skip]
let tiles = vec![ let tiles = vec![
Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall, Tile::Wall,
Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall, Tile::Wall, Tile::Empty, Tile::Empty, Tile::Empty, Tile::Wall,
@ -24,27 +35,33 @@ fn main() {
let level = engine::Level { let level = engine::Level {
width: 5, width: 5,
height: 5, height: 5,
tiles tiles,
}; };
engine.load_level(level); engine.load_level(level);
while let Some(event) = window.next() { while window.is_open() && !window.is_key_down(Key::Escape) {
if let Some(Button::Keyboard(key)) = event.press_args() { for i in buffer.iter_mut() {
match key { *i = 0; // write something more funny here!
Key::W | Key::Up => engine.add_movement(engine::Movement::Forward),
Key::S | Key::Down => engine.add_movement(engine::Movement::Backward),
Key::A | Key::Left => engine.add_movement(engine::Movement::TurnLeft),
Key::D | Key::Right => 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);
} }
// if let Some(Button::Keyboard(key)) = event.press_args() {
// match key {
// Key::W | Key::Up => engine.add_movement(engine::Movement::Forward),
// Key::S | Key::Down => engine.add_movement(engine::Movement::Backward),
// Key::A | Key::Left => engine.add_movement(engine::Movement::TurnLeft),
// Key::D | Key::Right => engine.add_movement(engine::Movement::TurnRight),
// _ => (),
// };
// };
engine.render(&mut buffer);
// if let Some(args) = event.update_args() {
// engine.update(args.dt);
// }
// We unwrap here as we want this code to exit if it fails.
// Real applications may want to handle this in a different way
window.update_with_buffer(&buffer, WIDTH, HEIGHT).unwrap();
} }
} }