1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
mod game;
mod renderer;
mod texture;
use game::{Game, GameState};
use minifb::{Key, Window, WindowOptions};
use renderer::Renderer;
use std::time::Instant;
const SCREEN_W: usize = 640;
const SCREEN_H: usize = 480;
fn main() {
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(
"Dungeon Crawler",
SCREEN_W,
SCREEN_H,
WindowOptions::default(),
)
.expect("Failed to create window");
let mut framebuffer = vec![0u32; SCREEN_W * SCREEN_H];
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;
// ---- 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);
// ---- 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);
}
}
// 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);
}
// ---- win check (placeholder — becomes staircase in Phase 1) ----
if game.check_win() {
println!("You found the exit in {} heartbeats!", game.heartbeats());
std::process::exit(0);
}
// ---- render ----
renderer.render(&game, &mut framebuffer);
window
.update_with_buffer(&framebuffer, SCREEN_W, SCREEN_H)
.unwrap();
// Sleep the remainder of the frame budget (saves CPU).
let elapsed = frame_start.elapsed();
if elapsed < frame_budget {
std::thread::sleep(frame_budget - elapsed);
}
}
}
|