rsnaker/controls/
playing_input.rs1use crate::controls::direction::Direction;
2use crate::controls::main_menu::{ENTER_KEYS, NEXT_KEYS, PREVIOUS_KEYS};
3use crate::game_logic::state::{GameOverMenu, GameState, GameStatus};
4use crossterm::event;
5use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
6use std::sync::{Arc, RwLock};
7use tracing::{error, info, warn};
8
9pub const QUIT_KEYS: [KeyCode; 3] = [KeyCode::Char('q'), KeyCode::Char('Q'), KeyCode::Tab];
10pub const START_KEYS: [KeyCode; 2] = [KeyCode::Char('r'), KeyCode::Char('R')];
11pub const MAIN_MENU_KEYS: [KeyCode; 3] = [KeyCode::Char('m'), KeyCode::Char('M'), KeyCode::Home];
12pub const PAUSE_KEYS: [KeyCode; 4] = [
14 KeyCode::Char('p'),
15 KeyCode::Char('P'),
16 KeyCode::Char(' '),
17 KeyCode::Char('-'),
18];
19pub const RESET_KEYS: [KeyCode; 2] = [KeyCode::Char('r'), KeyCode::Char('R')];
20#[must_use]
26pub fn has_no_modifiers(key: &KeyEvent) -> bool {
27 key.modifiers == KeyModifiers::NONE
28}
29
30pub fn playing_input_loop(direction: &Arc<RwLock<Direction>>, gs: &Arc<RwLock<GameState>>) {
37 loop {
38 if let Ok(event::Event::Key(key)) = event::read()
39 && key.kind == KeyEventKind::Press
40 && has_no_modifiers(&key)
41 {
42 let mut gs_guard = gs.write().unwrap();
43 if let GameStatus::GameOver(selection) = gs_guard.status {
45 if NEXT_KEYS.contains(&key.code) {
46 gs_guard.status = GameStatus::GameOver(selection.next());
47 } else if PREVIOUS_KEYS.contains(&key.code) {
48 gs_guard.status = GameStatus::GameOver(selection.previous());
49 } else if ENTER_KEYS.contains(&key.code) {
50 match selection {
51 GameOverMenu::Restart => {
52 info!("Restarting the game ! ");
53 gs_guard.status = GameStatus::Restarting;
54 }
55 GameOverMenu::Menu => {
56 info!("Coming back to menu ! ");
57 gs_guard.status = GameStatus::Menu;
58 break;
59 }
60 GameOverMenu::Quit => {
61 error!("You choose to quit the game 😶🌫️ ");
62 gs_guard.status = GameStatus::ByeBye;
63 break;
64 }
65 }
66 }
67 }
68 if PAUSE_KEYS.contains(&key.code) {
71 if gs_guard.status == GameStatus::Playing {
73 info!("Game paused ! ⏸️ ");
74 gs_guard.status = GameStatus::Paused;
75 } else if gs_guard.status == GameStatus::Paused {
76 info!("Game restart after pausing ! ⏯️ ");
77 gs_guard.status = GameStatus::Playing;
78 }
79 } else if QUIT_KEYS.contains(&key.code) {
81 error!("You choose to quit the game 😶🌫️ ");
82 gs_guard.status = GameStatus::ByeBye;
83 break;
84 } else if MAIN_MENU_KEYS.contains(&key.code) {
86 warn!("Going back to menu ! 🗺️");
87 gs_guard.status = GameStatus::Menu;
88 break;
89 } else if RESET_KEYS.contains(&key.code) {
91 warn!("Game hot restart ! 🤖");
92 gs_guard.status = GameStatus::Restarting;
93 } else {
95 let direction_input = match key.code {
96 KeyCode::Left => Some(Direction::Left),
97 KeyCode::Right => Some(Direction::Right),
98 KeyCode::Down => Some(Direction::Down),
99 KeyCode::Up => Some(Direction::Up),
100 _ => None,
101 };
102 if let Some(dir) = direction_input {
103 *direction.write().unwrap() = dir;
104 }
105 }
106 }
107 }
108}