change window dep from piston to minifb
This commit is contained in:
parent
4620f647ad
commit
3844c0fe80
1569
Cargo.lock
generated
1569
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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
3
rust-toolchain.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "1.56.1"
|
||||||
|
components = [ "rustfmt", "clippy" ]
|
155
src/engine.rs
155
src/engine.rs
|
@ -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);
|
||||||
|
|
71
src/main.rs
71
src/main.rs
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue