diff options
| author | salmonik <raisersoft@proton.me> | 2026-07-09 23:27:55 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-07-09 23:27:55 +0200 |
| commit | 3460d889aa2e7af1a60d218a1a8589027b4e4e63 (patch) | |
| tree | 89e66acd05fba086835337bfa95b36710dc8c4da /src/main.rs | |
| download | dungeon-3460d889aa2e7af1a60d218a1a8589027b4e4e63.tar.gz dungeon-3460d889aa2e7af1a60d218a1a8589027b4e4e63.zip | |
init
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d51fdfd --- /dev/null +++ b/src/main.rs | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | mod game; | ||
| 2 | mod renderer; | ||
| 3 | mod texture; | ||
| 4 | |||
| 5 | use game::Game; | ||
| 6 | use minifb::{Key, Window, WindowOptions}; | ||
| 7 | use renderer::Renderer; | ||
| 8 | use std::time::Instant; | ||
| 9 | |||
| 10 | const SCREEN_W: usize = 640; | ||
| 11 | const SCREEN_H: usize = 480; | ||
| 12 | |||
| 13 | fn main() { | ||
| 14 | println!("=== DOOM-LIKE MAZE ==="); | ||
| 15 | println!("Find the exit!"); | ||
| 16 | println!(" W / Up — forward"); | ||
| 17 | println!(" S / Down — backward"); | ||
| 18 | println!(" A / D — strafe left / right"); | ||
| 19 | println!(" ← / → — turn"); | ||
| 20 | println!(" Esc — quit\n"); | ||
| 21 | |||
| 22 | let mut game = Game::new(); | ||
| 23 | let renderer = Renderer::new(SCREEN_W, SCREEN_H); | ||
| 24 | |||
| 25 | let mut window = Window::new( | ||
| 26 | "Maze — Find the Exit!", | ||
| 27 | SCREEN_W, | ||
| 28 | SCREEN_H, | ||
| 29 | WindowOptions::default(), | ||
| 30 | ) | ||
| 31 | .expect("Failed to create window"); | ||
| 32 | |||
| 33 | let mut framebuffer = vec![0u32; SCREEN_W * SCREEN_H]; | ||
| 34 | let mut last = Instant::now(); | ||
| 35 | let frame_budget = std::time::Duration::from_micros(16600); // ~60 fps | ||
| 36 | |||
| 37 | while window.is_open() && !window.is_key_down(Key::Escape) { | ||
| 38 | let frame_start = Instant::now(); | ||
| 39 | let dt = (frame_start - last).as_secs_f64().min(0.1); | ||
| 40 | last = frame_start; | ||
| 41 | |||
| 42 | // ---- input ---- | ||
| 43 | let move_speed = 2.8; | ||
| 44 | let turn_speed = 2.8; | ||
| 45 | let strafe_speed = 2.2; | ||
| 46 | |||
| 47 | if window.is_key_down(Key::Left) { | ||
| 48 | game.rotate(-turn_speed * dt); | ||
| 49 | } | ||
| 50 | if window.is_key_down(Key::Right) { | ||
| 51 | game.rotate(turn_speed * dt); | ||
| 52 | } | ||
| 53 | // Combine forward + strafe into one displacement (prevents two-step | ||
| 54 | // wall clipping when pressing W+D / W+A near a wall). | ||
| 55 | let fwd = if window.is_key_down(Key::W) || window.is_key_down(Key::Up) { | ||
| 56 | move_speed * dt | ||
| 57 | } else if window.is_key_down(Key::S) || window.is_key_down(Key::Down) { | ||
| 58 | -move_speed * dt | ||
| 59 | } else { | ||
| 60 | 0.0 | ||
| 61 | }; | ||
| 62 | let strf = if window.is_key_down(Key::D) { | ||
| 63 | strafe_speed * dt | ||
| 64 | } else if window.is_key_down(Key::A) { | ||
| 65 | -strafe_speed * dt | ||
| 66 | } else { | ||
| 67 | 0.0 | ||
| 68 | }; | ||
| 69 | game.apply_movement(fwd, strf); | ||
| 70 | |||
| 71 | // ---- win condition ---- | ||
| 72 | if game.check_win() { | ||
| 73 | println!("🎉 You found the exit! Generating a new maze…"); | ||
| 74 | game = Game::new(); | ||
| 75 | last = Instant::now(); // avoid huge dt spike | ||
| 76 | } | ||
| 77 | |||
| 78 | // ---- render ---- | ||
| 79 | renderer.render(&game, &mut framebuffer); | ||
| 80 | window | ||
| 81 | .update_with_buffer(&framebuffer, SCREEN_W, SCREEN_H) | ||
| 82 | .unwrap(); | ||
| 83 | |||
| 84 | // Sleep the remainder of the frame budget (saves CPU). | ||
| 85 | let elapsed = frame_start.elapsed(); | ||
| 86 | if elapsed < frame_budget { | ||
| 87 | std::thread::sleep(frame_budget - elapsed); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
