Initial commit
This commit is contained in:
commit
a8f0ecf390
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
||||
63
Cargo.lock
generated
Normal file
63
Cargo.lock
generated
Normal 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
9
Cargo.toml
Normal 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
250
src/game.rs
Normal 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
8
src/main.rs
Normal file
@ -0,0 +1,8 @@
|
||||
mod game;
|
||||
|
||||
use crate::game::Game;
|
||||
|
||||
pub fn main() {
|
||||
let mut game = Game::new();
|
||||
game.run();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user