blizzard_engine/core/
network_application.rs1use std::sync::mpsc::Receiver;
6use std::sync::{Arc, Mutex};
7use std::thread;
8use std::time::{Duration, Instant};
9
10use crate::core::logger::initialize_logging;
11use crate::game::Game;
12
13pub struct Application<T: Game<K, I>, K, I> {
27 pub is_running: bool,
28 pub shared_state: Arc<Mutex<K>>,
29 is_suspended: bool,
30 last_time: Instant,
31 frames_per_second: Duration,
32 input: Arc<Mutex<I>>,
33 game: T,
34}
35
36impl<T: Game<K, I>, K, I> Clone for Application<T, K, I>
37where
38 T: Clone,
39 K: Copy,
40 I: Copy,
41{
42 fn clone(&self) -> Application<T, K, I> {
43 Application {
44 is_running: self.is_running,
45 shared_state: Arc::new(Mutex::new(*self.shared_state.lock().unwrap())),
46 is_suspended: self.is_suspended,
47 last_time: self.last_time,
48 frames_per_second: self.frames_per_second,
49 input: Arc::new(Mutex::new(*self.input.lock().unwrap())),
50 game: self.game.clone(),
51 }
52 }
53}
54
55impl<T: Game<K, I>, K, I> Application<T, K, I> {
56 fn create(game: T, shared_state: K, input: I, game_update_rate: i32) -> Application<T, K, I> {
59 initialize_logging();
61
62 Application {
64 is_running: false,
65 is_suspended: false,
66 last_time: Instant::now(),
67 frames_per_second: Duration::from_millis((1000 / game_update_rate) as u64), input: Arc::new(Mutex::new(input)),
69 shared_state: Arc::new(Mutex::new(shared_state)),
70 game,
71 }
72 }
73
74 pub fn start<M>(
77 &mut self,
78 receiver: Receiver<M>,
79 handle_input: &'static (dyn Fn(Receiver<M>, Arc<Mutex<I>>) -> I + Sync),
80 ) where
81 M: Send,
82 I: Send + Copy,
83 {
84 self.is_running = true;
85
86 self.game.world_config();
88
89 let input_copy = Arc::clone(&self.input);
90
91 thread::spawn(move || {
93 handle_input(receiver, input_copy);
94 });
95
96 while self.is_running {
98 let sleep_time = self.frames_per_second - self.last_time.elapsed();
100 thread::sleep(sleep_time);
101
102 self.last_time = Instant::now();
104
105 self.game
107 .update(*self.input.lock().unwrap(), Arc::clone(&self.shared_state));
108
109 self.game.reset_input(Arc::clone(&self.input));
111 self.is_running = !self.game.end_game();
115 }
116 }
117}
118
119pub fn create_app<T: Game<K, I>, K, I>(
121 game: T,
122 shared_state: K,
123 input: I,
124 game_update_rate: i32,
125) -> Application<T, K, I> {
126 Application::create(game, shared_state, input, game_update_rate)
127}