rustle_bird/
state.rs

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}