rsnaker/game_logic/
playing_logic.rs1use crate::controls::direction::Direction;
2use crate::controls::input::GreetingOption::StartGame;
3use crate::controls::input::{greeting_screen_manage_input, GreetingOption};
4use crate::game_logic::fruits_manager::FruitsManager;
5use crate::game_logic::state::{GameState, GameStatus};
6use crate::graphics::menus::greeting_menu::main_greeting_menu;
7use crate::graphics::sprites::fruit::Fruit;
8use crate::graphics::sprites::map::Map;
9use crate::graphics::sprites::snake_body::SnakeBody;
10use ratatui::DefaultTerminal;
11use std::sync::{Arc, RwLock};
12use std::thread::sleep;
13use std::time::Duration;
14
15pub fn playing_logic_loop(
18 direction: &Arc<RwLock<Direction>>,
19 snake: &Arc<RwLock<SnakeBody>>,
20 gs: &Arc<RwLock<GameState>>,
21 carte: &Arc<RwLock<Map>>,
22 fruits_manager: &Arc<RwLock<FruitsManager>>,
23 (game_speed, speed_score_modifier, classic_mode): (u64, u16, bool),
24) {
25 let mut gsc;
26 loop {
27 gsc = gs.read().unwrap().status.clone();
30 match gsc {
32 GameStatus::Playing => {
33 let mut write_guard = snake.write().unwrap();
34 let position = write_guard.ramp(&direction.read().unwrap(), &carte.read().unwrap());
36 let fruits = fruits_manager.read().unwrap().eat_some_fruits(position);
38 if let Some(fruits) = fruits {
40 let score_fruits = fruits.iter().map(Fruit::get_score).sum::<i32>();
41 let size_effect = fruits.iter().map(Fruit::get_grow_snake).sum::<i16>();
42 if !(classic_mode && size_effect <= 0) {
44 write_guard.relative_size_change(size_effect);
45 }
46 gs.write().unwrap().score += score_fruits * i32::from(speed_score_modifier);
50 fruits_manager.write().unwrap().replace_fruits(&fruits);
51 }
52 if write_guard.is_snake_eating_itself() {
54 let mut state_guard = gs.write().unwrap();
56 if (state_guard.life) >= 1 {
57 state_guard.life -= 1;
58 }
59 if state_guard.life == 0 {
60 state_guard.status = GameStatus::GameOver;
61 }
62 }
63 }
64 GameStatus::Restarting => {
65 sleep(Duration::from_millis(1000));
67 gs.write().unwrap().reset();
68 snake.write().unwrap().reset();
69 *direction.write().unwrap() = Direction::Right;
70 }
72 GameStatus::ByeBye | GameStatus::Menu => break,
73 GameStatus::Paused | GameStatus::GameOver => {}
74 }
75 sleep(Duration::from_millis(game_speed));
76 }
77}
78pub fn controls_greeting_screen(terminal: &mut DefaultTerminal) -> bool {
86 let mut stay = true;
87 let mut action: Option<GreetingOption> = None;
88 main_greeting_menu(terminal, &None, &StartGame);
89 let mut selected = 3;
92 let selection: [GreetingOption; 6] = [
93 GreetingOption::MainMenu,
94 GreetingOption::Fruits,
95 GreetingOption::Velocity,
96 GreetingOption::StartGame,
97 GreetingOption::Parameters,
98 GreetingOption::Help,
99 ];
100 while stay {
101 let current = greeting_screen_manage_input();
102 if current.is_some() {
104 if current == Some(GreetingOption::Next) {
106 selected = (selected + 1) % selection.len();
107 } else if current == Some(GreetingOption::Previous) {
108 selected = (selected + selection.len() - 1) % selection.len();
110 }
111 else if current == Some(GreetingOption::Enter) {
113 action = Some(selection[selected].clone());
114 } else {
115 action = current;
116 }
117 }
118 main_greeting_menu(terminal, &action, &selection[selected]);
120 if let Some(GreetingOption::StartGame | GreetingOption::QuitGame) = action {
121 stay = false;
122 }
123 }
124 action == Some(GreetingOption::StartGame)
125}