rsnaker/game_logic/
playing_logic.rs1use crate::controls::direction::Direction;
2use crate::controls::speed::Speed;
3use crate::game_logic::fruits_manager::FruitsManager;
4use crate::game_logic::high_score::{HighScore, HighScoreManager};
5use crate::game_logic::state::{GameOverMenu, GameState, GameStatus};
6use crate::graphics::sprites::fruit::Fruit;
7use crate::graphics::sprites::map::Map;
8use crate::graphics::sprites::snake_body::SnakeBody;
9use std::sync::{Arc, RwLock};
10use std::thread::sleep;
11use std::time::Duration;
12
13pub fn playing_logic_loop(
17 direction: &Arc<RwLock<Direction>>,
18 snake: &Arc<RwLock<SnakeBody>>,
19 gs: &Arc<RwLock<GameState>>,
20 carte: &Arc<RwLock<Map>>,
21 fruits_manager: &Arc<RwLock<FruitsManager>>,
22 (game_speed, snake_symbols, classic_mode): (Speed, String, bool),
23) {
24 let mut gsc;
25 loop {
26 gsc = gs.read().unwrap().status.clone();
29 match gsc {
31 GameStatus::Playing => {
32 let mut write_guard = snake.write().unwrap();
33 let position = write_guard.ramp(&direction.read().unwrap(), &carte.read().unwrap());
35 let fruits = fruits_manager.read().unwrap().eat_some_fruits(position);
37 if let Some(fruits) = fruits {
39 let score_fruits = fruits.iter().map(Fruit::get_score).sum::<i32>();
40 let size_effect = fruits.iter().map(Fruit::get_grow_snake).sum::<i16>();
41 if !(classic_mode && size_effect <= 0) {
43 write_guard.relative_size_change(size_effect);
44 }
45 let fruit_impact = score_fruits * i32::from(game_speed.score_modifier());
49 let mut state_guard_gs = gs.write().unwrap();
50 if fruit_impact < 0 {
52 state_guard_gs.score = state_guard_gs
53 .score
54 .saturating_sub(fruit_impact.unsigned_abs());
55 } else {
56 state_guard_gs.score = state_guard_gs
57 .score
58 .saturating_add(fruit_impact.unsigned_abs());
59 }
60 fruits_manager.write().unwrap().replace_fruits(&fruits);
61 }
62 if write_guard.is_snake_eating_itself() {
64 let mut state_guard = gs.write().unwrap();
66 if (state_guard.life) >= 1 {
67 state_guard.life -= 1;
68 }
69 if state_guard.life == 0 {
70 state_guard.status = GameStatus::GameOver(GameOverMenu::default());
72
73 if let Ok(manager) = HighScoreManager::new() {
75 let score_value: u32 = state_guard.score;
76 let _ = manager.save_score(&HighScore::new(
77 snake_symbols.clone(),
78 score_value,
79 game_speed.to_string(),
81 ));
82 state_guard.rank = manager.get_rank(score_value).unwrap_or(None);
83 }
84 }
85 }
86 }
87 GameStatus::Restarting => {
88 sleep(Duration::from_millis(1000));
90 gs.write().unwrap().reset();
91 snake.write().unwrap().reset();
92 *direction.write().unwrap() = Direction::Right;
93 fruits_manager.write().unwrap().reset();
94 }
96 GameStatus::ByeBye | GameStatus::Menu => break,
97 GameStatus::Paused | GameStatus::GameOver(_) => {}
98 }
99 sleep(Duration::from_millis(game_speed.ms_value()));
100 }
101}