From c8eae871002b57f45b29a2d158e384433e76a90c Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 10 Jul 2026 21:16:59 +0200 Subject: Phase 2 --- src/main.rs | 145 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 39 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index d51fdfd..391bb90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ mod game; mod renderer; mod texture; -use game::Game; +use game::{Game, GameState}; use minifb::{Key, Window, WindowOptions}; use renderer::Renderer; use std::time::Instant; @@ -11,19 +11,22 @@ const SCREEN_W: usize = 640; const SCREEN_H: usize = 480; fn main() { - println!("=== DOOM-LIKE MAZE ==="); - println!("Find the exit!"); - println!(" W / Up — forward"); - println!(" S / Down — backward"); - println!(" A / D — strafe left / right"); - println!(" ← / → — turn"); - println!(" Esc — quit\n"); + println!("=== DUNGEON CRAWLER ==="); + println!(" W / S — forward / backward"); + println!(" A / D — strafe left / right"); + println!(" Q / E — turn 90° left / right"); + println!(" Space — attack"); + println!(" Z — use selected inventory item"); + println!(" X — discard selected inventory item"); + println!(" 1-4 — select inventory slot"); + println!(" C — skip turn"); + println!(" Esc — quit\n"); let mut game = Game::new(); let renderer = Renderer::new(SCREEN_W, SCREEN_H); let mut window = Window::new( - "Maze — Find the Exit!", + "Dungeon Crawler", SCREEN_W, SCREEN_H, WindowOptions::default(), @@ -34,45 +37,109 @@ fn main() { let mut last = Instant::now(); let frame_budget = std::time::Duration::from_micros(16600); // ~60 fps + // Track previous key state for edge-triggered actions. + let mut prev_w = false; + let mut prev_s = false; + let mut prev_a = false; + let mut prev_d = false; + let mut prev_q = false; + let mut prev_e = false; + let mut prev_space = false; + let mut prev_z = false; + let mut prev_x = false; + let mut prev_c = false; + let mut prev_1 = false; + let mut prev_2 = false; + let mut prev_3 = false; + let mut prev_4 = false; + while window.is_open() && !window.is_key_down(Key::Escape) { let frame_start = Instant::now(); let dt = (frame_start - last).as_secs_f64().min(0.1); last = frame_start; - // ---- input ---- - let move_speed = 2.8; - let turn_speed = 2.8; - let strafe_speed = 2.2; + // ---- read current key states ---- + let cur_w = window.is_key_down(Key::W); + let cur_s = window.is_key_down(Key::S); + let cur_a = window.is_key_down(Key::A); + let cur_d = window.is_key_down(Key::D); + let cur_q = window.is_key_down(Key::Q); + let cur_e = window.is_key_down(Key::E); + let cur_space = window.is_key_down(Key::Space); + let cur_z = window.is_key_down(Key::Z); + let cur_x = window.is_key_down(Key::X); + let cur_c = window.is_key_down(Key::C); + let cur_1 = window.is_key_down(Key::Key1); + let cur_2 = window.is_key_down(Key::Key2); + let cur_3 = window.is_key_down(Key::Key3); + let cur_4 = window.is_key_down(Key::Key4); - if window.is_key_down(Key::Left) { - game.rotate(-turn_speed * dt); + // ---- input (edge-triggered, only in WaitingForInput) ---- + if game.can_act() { + if cur_w && !prev_w { + game.move_forward(); + } else if cur_s && !prev_s { + game.move_backward(); + } else if cur_a && !prev_a { + game.strafe_left(); + } else if cur_d && !prev_d { + game.strafe_right(); + } else if cur_q && !prev_q { + game.turn_left(); + } else if cur_e && !prev_e { + game.turn_right(); + } else if cur_space && !prev_space { + game.attack(); + } else if cur_z && !prev_z { + game.use_item(); + } else if cur_x && !prev_x { + game.discard_item(); + } else if cur_c && !prev_c { + game.skip_turn(); + } else if cur_1 && !prev_1 { + game.select_slot(0); + } else if cur_2 && !prev_2 { + game.select_slot(1); + } else if cur_3 && !prev_3 { + game.select_slot(2); + } else if cur_4 && !prev_4 { + game.select_slot(3); + } } - if window.is_key_down(Key::Right) { - game.rotate(turn_speed * dt); + + // Update previous states. + prev_w = cur_w; + prev_s = cur_s; + prev_a = cur_a; + prev_d = cur_d; + prev_q = cur_q; + prev_e = cur_e; + prev_space = cur_space; + prev_z = cur_z; + prev_x = cur_x; + prev_c = cur_c; + prev_1 = cur_1; + prev_2 = cur_2; + prev_3 = cur_3; + prev_4 = cur_4; + + // ---- advance animations / state machine ---- + game.update_animation(dt); + + // ---- death check ---- + if game.state == GameState::GameOver { + let score = (game.kills * 100) + (game.depth.pow(2) * 50) + 500; // fists = base damage 1 + println!( + "You had become yet another legend of this dungeon.\nScore: {}", + score + ); + std::process::exit(0); } - // Combine forward + strafe into one displacement (prevents two-step - // wall clipping when pressing W+D / W+A near a wall). - let fwd = if window.is_key_down(Key::W) || window.is_key_down(Key::Up) { - move_speed * dt - } else if window.is_key_down(Key::S) || window.is_key_down(Key::Down) { - -move_speed * dt - } else { - 0.0 - }; - let strf = if window.is_key_down(Key::D) { - strafe_speed * dt - } else if window.is_key_down(Key::A) { - -strafe_speed * dt - } else { - 0.0 - }; - game.apply_movement(fwd, strf); - - // ---- win condition ---- + + // ---- win check (placeholder — becomes staircase in Phase 1) ---- if game.check_win() { - println!("🎉 You found the exit! Generating a new maze…"); - game = Game::new(); - last = Instant::now(); // avoid huge dt spike + println!("You found the exit in {} heartbeats!", game.heartbeats()); + std::process::exit(0); } // ---- render ---- -- cgit v1.2.3