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}