basic/
basic.rs

1use std::{fmt::format, time::Duration};
2
3use bracket_lib::prelude::*;
4use bracket_state_machine::prelude::*;
5
6pub type TransitionResult = (StateTransition<Game, ModeResult>, TransitionControl);
7
8#[derive(Default)]
9struct TitleState;
10struct PausedState;
11
12#[derive(Clone)]
13pub enum TitleResult {
14    Quit,
15}
16
17#[derive(Clone)]
18pub enum ModeResult {
19    TitleResult(TitleResult),
20    PausedResult(PausedResult),
21}
22
23impl State for TitleState {
24    type State = Game;
25    type StateResult = ModeResult;
26
27    fn update(
28        &mut self,
29        term: &mut BTerm,
30        state: &mut Self::State,
31        _pop_result: &Option<Self::StateResult>,
32        dt: Duration,
33    ) -> TransitionResult {
34        if let Some(key) = term.key {
35            match key {
36                VirtualKeyCode::Escape => {
37                    return (StateTransition::Terminate, TransitionControl::Update);
38                }
39                VirtualKeyCode::Space => {
40                    return (
41                        StateTransition::Push(Box::new(PausedState)),
42                        TransitionControl::Update,
43                    );
44                }
45                VirtualKeyCode::Up => {
46                    state.num += 1;
47                }
48                VirtualKeyCode::Down => {
49                    state.num -= 1;
50                }
51                _ => {}
52            }
53
54            if key == VirtualKeyCode::Space {
55                return (
56                    Transition::Push(Box::new(PausedState)),
57                    TransitionControl::Update,
58                );
59            }
60        }
61
62        (Transition::Stay, TransitionControl::Update)
63    }
64
65    fn render(&self, term: &mut BTerm, state: &Self::State, active: bool) {
66        term.print(
67            1,
68            2,
69            "Press [UP] to increment counter and [DOWN] to decrement counter.",
70        );
71        term.print(1, 4, "Press [ESC] to close & [SPACE] to transition");
72        term.print(1, 6, format!("State: {:?}", state));
73    }
74
75    fn clear(&self, _state: &Self::State, _term: &mut BTerm) {
76        BACKEND_INTERNAL
77            .lock()
78            .consoles
79            .iter_mut()
80            .for_each(|c| c.console.cls());
81    }
82
83    fn is_transparent(&self) -> bool {
84        true
85    }
86}
87
88#[derive(Clone)]
89pub enum PausedResult {
90    Resume,
91    Quit,
92}
93
94impl State for PausedState {
95    type State = Game;
96    type StateResult = ModeResult;
97
98    fn update(
99        &mut self,
100        term: &mut BTerm,
101        state: &mut Self::State,
102        _pop_result: &Option<ModeResult>,
103        _dt: Duration,
104    ) -> TransitionResult {
105        if let Some(key) = term.key {
106            if key == VirtualKeyCode::Space {
107                return (
108                    Transition::Pop(ModeResult::PausedResult(PausedResult::Resume)),
109                    TransitionControl::Update,
110                );
111            }
112        }
113
114        (Transition::Stay, TransitionControl::Update)
115    }
116
117    fn render(&self, term: &mut BTerm, state: &Self::State, active: bool) {
118        term.print_centered(0, format!("PAUSED {:?}", state));
119    }
120}
121
122#[derive(Debug)]
123pub struct Game {
124    pub num: i32,
125}
126
127fn main() -> BError {
128    let context = BTermBuilder::simple80x50()
129        .with_title("State Machine Sample")
130        .with_dimensions(100, 70)
131        .with_fps_cap(24.0)
132        .build()
133        .expect("failed to build a BTerm");
134
135    let machine = StateMachine::new(Game { num: 0 }, TitleState::default());
136    main_loop(context, machine)
137}