rsnaker/game_logic/
playing_thread_manager.rs1pub use crate::controls::direction::Direction;
2use crate::controls::input::playing_input_loop;
3pub use crate::controls::speed::Speed;
4pub use crate::game_logic::fruits_manager::FruitsManager;
5use crate::game_logic::game_options::GameOptions;
6use crate::game_logic::playing_logic::{controls_greeting_screen, playing_logic_loop};
7pub use crate::game_logic::state::{GameState, GameStatus};
8use crate::graphics::playing_render::playing_render_loop;
9use crate::graphics::sprites::map::Map;
10use crate::graphics::sprites::snake_body::SnakeBody;
11use ratatui::DefaultTerminal;
12use std::sync::{Arc, RwLock};
13use std::thread;
14
15pub struct Game<'a, 'b, 'c: 'b> {
18 options: GameOptions,
20 speed: Speed,
22 serpent: Arc<RwLock<SnakeBody<'a>>>,
24 direction: Arc<RwLock<Direction>>,
26 carte: Arc<RwLock<Map<'b>>>,
29 state: Arc<RwLock<GameState>>,
31 fruits_manager: Arc<RwLock<FruitsManager<'c, 'b>>>,
33 terminal: DefaultTerminal,
35}
36impl<'a, 'b, 'c> Game<'a, 'b, 'c> {
37 #[must_use]
38 pub fn new(
39 options: GameOptions,
40 serpent: SnakeBody<'a>,
41 carte: Map<'b>,
42 terminal: DefaultTerminal,
43 ) -> Game<'a, 'b, 'c> {
44 let arc_carte = Arc::new(RwLock::new(carte));
45 let life = options.life;
46 let fruits_nb = options.nb_of_fruit;
47 let speed = options.speed;
48 Game {
49 options,
50 speed,
51 serpent: Arc::new(RwLock::new(serpent)),
52 direction: Arc::new(RwLock::new(Direction::Right)),
53 carte: arc_carte.clone(),
54 state: Arc::new(RwLock::new(GameState::new(life))),
55 fruits_manager: Arc::new(RwLock::new(FruitsManager::new(
56 fruits_nb,
57 arc_carte.clone(),
58 ))),
59 terminal,
60 }
61 }
62 pub fn menu(&mut self) {
69 while self
71 .state
72 .read()
73 .expect("Panic in a previous thread, check previous error")
74 .status
75 != GameStatus::ByeBye
76 {
77 if controls_greeting_screen(&mut self.terminal) {
78 self.init();
79 self.start();
80 } else {
81 return;
82 }
83 }
84 }
85 fn init(&mut self) {
86 self.state.write().unwrap().reset();
88 self.serpent.write().unwrap().reset();
89 *self.direction.write().unwrap() = Direction::Right;
90 }
91 pub fn start(&mut self) {
93 let logic_snake = Arc::clone(&self.serpent);
99 let logic_gs = Arc::clone(&self.state);
100 let logic_dir = Arc::clone(&self.direction);
101 let carte = Arc::clone(&self.carte);
102 let fruits_manager = Arc::clone(&self.fruits_manager);
103
104 let input_gs = Arc::clone(&self.state);
106 let input_dir = Arc::clone(&self.direction);
107
108 let game_speed = self.speed.ms_value();
111 let speed_score_modifier = self.speed.score_modifier();
112 let classic = self.options.classic_mode;
113
114 thread::scope(|s| {
116 s.spawn(move || {
118 playing_logic_loop(
119 &logic_dir,
120 &logic_snake,
121 &logic_gs,
122 &carte,
123 &fruits_manager,
124 (game_speed, speed_score_modifier, classic),
125 );
126 });
127 s.spawn(move || {
129 playing_input_loop(&input_dir, &input_gs);
130 });
131
132 playing_render_loop(
134 &Arc::clone(&self.carte),
135 &Arc::clone(&self.fruits_manager),
136 &Arc::clone(&self.state),
137 &Arc::clone(&self.serpent),
138 self.options.uncaps_fps,
139 self.speed.symbol(),
140 &mut self.terminal,
141 );
142 });
143 }
144}