1use crate::components::{bird::Bird, map::Map};
2use crate::config::CONFIG;
3use bracket_lib::terminal::{BTerm, GameState, VirtualKeyCode};
4
5enum ExecState {
6 Ready,
7 Playing,
8 Pause,
9 Dead,
10}
11
12pub struct State {
13 mode: ExecState,
14 bird: Bird,
15 map: Map,
16 score: u32,
17}
18
19impl Default for State {
20 fn default() -> Self {
21 Self {
22 mode: ExecState::Ready,
23 bird: Bird::new(),
24 map: Map::new(),
25 score: 0,
26 }
27 }
28}
29
30impl State {
31 fn restart(&mut self) {
32 self.mode = ExecState::Playing;
33 self.bird.init();
34 self.map.init();
35 self.score = 0;
36 }
37
38 fn menu(&mut self, ctx: &mut BTerm) {
39 ctx.cls();
40 ctx.print_centered(7, "Rustle Bird");
41 ctx.print_centered(15, "Press any button to start");
42 ctx.print_centered(16, "Press Esc or Q to quit");
43
44 if let Some(key) = ctx.key {
45 match key {
46 VirtualKeyCode::Escape | VirtualKeyCode::Q => ctx.quitting = true,
47 _ => self.restart(),
48 }
49 }
50 }
51
52 fn play(&mut self, ctx: &mut BTerm) {
53 ctx.cls();
54 self.print_scene(ctx);
55
56 if let Some(key) = ctx.key {
57 match key {
58 VirtualKeyCode::P => self.mode = ExecState::Pause,
59 _ => self.bird.flap(),
60 }
61 }
62
63 if self.bird.get_height() < 0. || self.map.collide(CONFIG.width as f64 / 2., self.bird.get_height()) {
64 self.mode = ExecState::Dead;
65 }
66
67 self.bird.update();
68 if self.map.update() {
69 self.score += 1;
70 }
71 }
72
73 fn pause(&mut self, ctx: &mut BTerm) {
74 ctx.cls();
75 ctx.print_centered(7, "Pause");
76 self.print_scene(ctx);
77
78 if let Some(key) = ctx.key {
79 if key == VirtualKeyCode::P {
80 self.mode = ExecState::Playing
81 }
82 }
83 }
84
85 fn end(&mut self, ctx: &mut BTerm) {
86 ctx.cls();
87 ctx.print_centered(7, "You are dead");
88 ctx.print_centered(8, format!("Score: {:?}", self.score));
89 ctx.print_centered(15, "Press any button to restart");
90 ctx.print_centered(16, "Press Esc or Q to quit");
91
92 if let Some(key) = ctx.key {
93 match key {
94 VirtualKeyCode::Escape | VirtualKeyCode::Q => ctx.quitting = true,
95 _ => self.restart(),
96 }
97 }
98 }
99
100 fn print_scene(&self, ctx: &mut BTerm) {
101 self.map.print(ctx);
102 self.bird.print(ctx);
103 ctx.print(CONFIG.width - 5, 1, self.score);
104 }
105}
106
107impl GameState for State {
108 fn tick(&mut self, ctx: &mut BTerm) {
109 match self.mode {
110 ExecState::Ready => self.menu(ctx),
111 ExecState::Playing => self.play(ctx),
112 ExecState::Pause => self.pause(ctx),
113 ExecState::Dead => self.end(ctx),
114 }
115 }
116}