Initial commit

This commit is contained in:
Michael Smith 2023-03-26 20:52:46 +02:00
commit a8f0ecf390
5 changed files with 331 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

63
Cargo.lock generated Normal file
View File

@ -0,0 +1,63 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "doomclone"
version = "0.1.0"
dependencies = [
"sdl2",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]]
name = "sdl2"
version = "0.35.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a"
dependencies = [
"bitflags",
"lazy_static",
"libc",
"sdl2-sys",
]
[[package]]
name = "sdl2-sys"
version = "0.35.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0"
dependencies = [
"cfg-if",
"libc",
"version-compare",
]
[[package]]
name = "version-compare"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "doomclone"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sdl2 = "*"

250
src/game.rs Normal file
View File

@ -0,0 +1,250 @@
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::keyboard::Scancode;
use sdl2::pixels::Color;
use sdl2::rect::{Point, Rect};
use std::time::Duration;
const WIDTH: u32 = 640;
const HEIGHT: u32 = 480;
const FPS: u32 = 60;
struct Player {
x: i32,
y: i32,
z: i32,
a: i32,
l: i32,
}
struct M {
cos: [f64; 360],
sin: [f64; 360],
}
pub struct Game {
canvas: sdl2::render::WindowCanvas,
event_pump: sdl2::EventPump,
maths: M,
player: Player,
running: bool,
}
impl Game {
pub fn new() -> Game {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem
.window("Doom clone", WIDTH, HEIGHT)
.position_centered()
.build()
.unwrap();
let mut maths = M {
cos: [0.0; 360],
sin: [0.0; 360],
};
for x in 0..360 {
maths.cos[x] = (x as f64 / 180.0 * std::f64::consts::PI).cos();
maths.sin[x] = (x as f64 / 180.0 * std::f64::consts::PI).sin();
}
Game {
canvas: window.into_canvas().build().unwrap(),
maths: maths,
player: Player {
x: 70,
y: -110,
z: 20,
a: 0,
l: 0,
},
event_pump: sdl_context.event_pump().unwrap(),
running: false,
}
}
fn start(&mut self) {
self.running = true;
}
fn check_events(&mut self) {
for event in self.event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => self.running = false,
Event::KeyDown {
scancode: Some(Scancode::W),
..
} => {
let dx = self.maths.sin[self.player.a as usize] * 10.0;
let dy = self.maths.cos[self.player.a as usize] * 10.0;
self.player.x += dx as i32;
self.player.y += dy as i32;
}
Event::KeyDown {
scancode: Some(Scancode::A),
..
} => {
self.player.a -= 4;
if self.player.a < 0 {
self.player.a += 360;
};
}
Event::KeyDown {
scancode: Some(Scancode::S),
..
} => {
let dx = self.maths.sin[self.player.a as usize] * 10.0;
let dy = self.maths.cos[self.player.a as usize] * 10.0;
self.player.x -= dx as i32;
self.player.y -= dy as i32;
}
Event::KeyDown {
scancode: Some(Scancode::D),
..
} => {
self.player.a += 4;
if self.player.a > 359 {
self.player.a -= 360;
};
}
Event::KeyDown {
scancode: Some(Scancode::Q),
..
} => {
let dx = self.maths.sin[self.player.a as usize] * 10.0;
let dy = self.maths.cos[self.player.a as usize] * 10.0;
self.player.x -= dy as i32;
self.player.y += dx as i32;
}
Event::KeyDown {
scancode: Some(Scancode::E),
..
} => {
let dx = self.maths.sin[self.player.a as usize] * 10.0;
let dy = self.maths.cos[self.player.a as usize] * 10.0;
self.player.x += dy as i32;
self.player.y -= dx as i32;
}
Event::KeyDown {
keycode: Some(Keycode::Up),
..
} => {
self.player.l -= 1;
}
Event::KeyDown {
keycode: Some(Keycode::Down),
..
} => {
self.player.l += 1;
}
_ => {}
}
}
}
fn draw_wall(&mut self, x1: i32, x2: i32, b1: i32, b2: i32, t1: i32, t2: i32) {
// Hold difference in distance
let dyb = b2 - b1; // y distance of bottom line
let dyt = t2 - t1; // y distance of top line
let mut dx = x2 - x1; // x distance
if dx == 0 {
dx = 1;
}
let xs = x1; // hold initial x1 starting position
// draw x vertical lines
for x in x1..x2 {
// The Y start and end point
let y1 = dyb * (x - xs) / dx + b1; // y bottom point
let y2 = dyt * (x - xs) / dx + t1; // y top point
for y in y1..y2 {
self.canvas
.fill_rect(Rect::from_center(Point::new(x, y), 4, 4))
.unwrap();
}
}
}
fn update(&mut self) {
let mut wx = [0; 4];
let mut wy = [0; 4];
let mut wz = [0; 4];
let cs = self.maths.cos[self.player.a as usize];
let sn = self.maths.sin[self.player.a as usize];
// Offset bottom two points by player
let x1 = 40 - self.player.x;
let y1 = 10 - self.player.y;
let x2 = 40 - self.player.x;
let y2 = 290 - self.player.y;
// World x position
wx[0] = (x1 as f64 * cs - y1 as f64 * sn) as i32;
wx[1] = (x2 as f64 * cs - y2 as f64 * sn) as i32;
wx[2] = wx[0];
wx[2] = wx[1];
// World y position
wy[0] = (y1 as f64 * cs + x1 as f64 * sn) as i32;
wy[1] = (y2 as f64 * cs + x2 as f64 * sn) as i32;
wy[2] = wy[0];
wy[3] = wy[1];
// World z height
wz[0] = 0 - self.player.z + ((self.player.l * wy[0]) / 32);
wz[1] = 0 - self.player.z + ((self.player.l * wy[1]) / 32);
wz[2] = wz[0] + 40;
wz[3] = wz[1] + 40;
// Screen x, screen y position
wx[0] = wx[0] * 200 / wy[0] + (WIDTH / 2) as i32;
wy[0] = wz[0] * 200 / wy[0] + (HEIGHT / 2) as i32;
wx[1] = wx[1] * 200 / wy[1] + (WIDTH / 2) as i32;
wy[1] = wz[1] * 200 / wy[1] + (HEIGHT / 2) as i32;
wx[2] = wx[2] * 200 / wy[2] + (WIDTH / 2) as i32;
wy[2] = wz[2] * 200 / wy[2] + (HEIGHT / 2) as i32;
wx[3] = wx[3] * 200 / wy[3] + (WIDTH / 2) as i32;
wy[3] = wz[3] * 200 / wy[3] + (HEIGHT / 2) as i32;
self.canvas.set_draw_color(Color::RGB(255, 255, 0));
self.draw_wall(wx[0], wx[1], wy[0], wy[1], wy[2], wy[3]);
}
fn render(&mut self) {
self.canvas.set_draw_color(Color::RGB(0, 0, 255));
self.canvas.clear();
self.update();
self.canvas.present();
}
pub fn run(&mut self) {
self.start();
while self.running {
self.check_events();
self.update();
self.render();
std::thread::sleep(Duration::new(0, 1_000_000_000 / FPS));
}
}
}

8
src/main.rs Normal file
View File

@ -0,0 +1,8 @@
mod game;
use crate::game::Game;
pub fn main() {
let mut game = Game::new();
game.run();
}