From a8f0ecf3904f50c14619f64902d40978f5807a23 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Sun, 26 Mar 2023 20:52:46 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + Cargo.lock | 63 +++++++++++++ Cargo.toml | 9 ++ src/game.rs | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 8 ++ 5 files changed, 331 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/game.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3d6730c --- /dev/null +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9e912f1 --- /dev/null +++ b/Cargo.toml @@ -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 = "*" diff --git a/src/game.rs b/src/game.rs new file mode 100644 index 0000000..24e3466 --- /dev/null +++ b/src/game.rs @@ -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)); + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f5dcbf8 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,8 @@ +mod game; + +use crate::game::Game; + +pub fn main() { + let mut game = Game::new(); + game.run(); +}