game_loop/
helper.rs

1use crate::*;
2
3pub use helper::*;
4
5#[cfg(all(not(target_arch = "wasm32"), not(feature="winit"), not(feature="tao")))]
6mod helper {
7    use super::*;
8
9    pub fn game_loop<G, U, R>(game: G, updates_per_second: u32, max_frame_time: f64, mut update: U, mut render: R) -> GameLoop<G, Time, ()>
10        where U: FnMut(&mut GameLoop<G, Time, ()>),
11              R: FnMut(&mut GameLoop<G, Time, ()>),
12    {
13        let mut game_loop = GameLoop::new(game, updates_per_second, max_frame_time, ());
14
15        while game_loop.next_frame(&mut update, &mut render) {}
16
17        game_loop
18    }
19}
20
21#[cfg(all(target_arch = "wasm32", not(feature = "winit")))]
22mod helper {
23    use super::*;
24    use web_sys::window;
25    use wasm_bindgen::JsCast;
26    use wasm_bindgen::closure::Closure;
27
28    pub fn game_loop<G, U, R>(game: G, updates_per_second: u32, max_frame_time: f64, update: U, render: R)
29        where G: 'static,
30              U: FnMut(&mut GameLoop<G, Time, ()>) + 'static,
31              R: FnMut(&mut GameLoop<G, Time, ()>) + 'static,
32    {
33        let game_loop = GameLoop::new(game, updates_per_second, max_frame_time, ());
34
35        animation_frame(game_loop, update, render);
36    }
37
38    fn animation_frame<G, U, R>(mut g: GameLoop<G, Time, ()>, mut update: U, mut render: R)
39        where G: 'static,
40              U: FnMut(&mut GameLoop<G, Time, ()>) + 'static,
41              R: FnMut(&mut GameLoop<G, Time, ()>) + 'static,
42    {
43        if g.next_frame(&mut update, &mut render) {
44            let next_frame = move || animation_frame(g, update, render);
45            let closure = Closure::once_into_js(next_frame);
46            let js_func = closure.as_ref().unchecked_ref();
47
48            window().unwrap().request_animation_frame(js_func).unwrap();
49        }
50    }
51}
52
53#[cfg(feature="winit")]
54mod helper {
55    use std::sync::Arc;
56    use super::*;
57    use winit::event::{Event, WindowEvent};
58    use winit::event_loop::{ControlFlow, EventLoop};
59    use winit::error::EventLoopError;
60    use winit::window::Window;
61
62    pub use winit;
63
64    pub fn game_loop<G, U, R, H, T>(event_loop: EventLoop<T>, window: Arc<Window>, game: G, updates_per_second: u32, max_frame_time: f64, mut update: U, mut render: R, mut handler: H) -> Result<(), EventLoopError>
65        where G: 'static,
66              U: FnMut(&mut GameLoop<G, Time, Arc<Window>>) + 'static,
67              R: FnMut(&mut GameLoop<G, Time, Arc<Window>>) + 'static,
68              H: FnMut(&mut GameLoop<G, Time, Arc<Window>>, &Event<T>) + 'static,
69              T: 'static,
70    {
71        let mut game_loop = GameLoop::new(game, updates_per_second, max_frame_time, window);
72
73        event_loop.run(move |event, window_target| {
74            window_target.set_control_flow(ControlFlow::Poll);
75
76            // Forward events to existing handlers.
77            handler(&mut game_loop, &event);
78
79            match event {
80                Event::AboutToWait => {
81                    game_loop.window.request_redraw();
82                },
83                Event::WindowEvent { event: WindowEvent::Occluded(occluded), .. } => {
84                    game_loop.window_occluded = occluded;
85                },
86                Event::WindowEvent { event: WindowEvent::RedrawRequested, .. } => {
87                    if !game_loop.next_frame(&mut update, &mut render) {
88                        window_target.exit();
89                    }
90                },
91                _ => {},
92            }
93        })
94    }
95}
96
97#[cfg(feature = "tao")]
98mod helper {
99    use super::*;
100    use tao::event::Event;
101    use tao::event_loop::{ControlFlow, EventLoop};
102    use tao::window::Window;
103    use std::sync::Arc;
104
105    pub use tao;
106
107    pub fn game_loop<G, U, R, H, T>(event_loop: EventLoop<T>, window: Arc<Window>, game: G, updates_per_second: u32, max_frame_time: f64, mut update: U, mut render: R, mut handler: H) -> !
108        where G: 'static,
109              U: FnMut(&mut GameLoop<G, Time, Arc<Window>>) + 'static,
110              R: FnMut(&mut GameLoop<G, Time, Arc<Window>>) + 'static,
111              H: FnMut(&mut GameLoop<G, Time, Arc<Window>>, &Event<'_, T>) + 'static,
112              T: 'static,
113    {
114        let mut game_loop = GameLoop::new(game, updates_per_second, max_frame_time, window);
115
116        event_loop.run(move |event, _, control_flow| {
117            *control_flow = ControlFlow::Poll;
118
119            // Forward events to existing handlers.
120            handler(&mut game_loop, &event);
121
122            match event {
123                Event::RedrawRequested(_) => {
124                    if !game_loop.next_frame(&mut update, &mut render) {
125                        *control_flow = ControlFlow::Exit;
126                    }
127                },
128                Event::MainEventsCleared => {
129                    game_loop.window.request_redraw();
130                },
131                _ => {},
132            }
133        })
134    }
135}