-
Notifications
You must be signed in to change notification settings - Fork 27
3. Main Loop
In your main game loop, you should call advance_frame()
in fixed intervals. How to do that exactly depends heavily on your software stack. You can also check out 👉this article or 👉this article to learn more about running your own gameloop.
For full code examples, take a look at:
sess.poll_remote_clients();
Polling remote clients will receive and handle incoming UDP packets and send queued packets to other remote clients. In order to establish a connection between sessions, call this function repeatedly until sessions are synchronized. While the game is running and you are calling advance_frame()
regularily, GGRS works without calling this method, but frequent polling leads to timely communication between sessions. If you have spare time between rendering and updating your game, poll remote clients.
// time variables for tick rate
let mut last_update = Instant::now();
let mut accumulator = Duration::ZERO;
loop {
// communicate, receive and send packets
sess.poll_remote_clients();
// print GGRS events
for event in sess.events() {
println!("Event: {:?}", event);
}
// frames are only happening if the sessions are synchronized
if sess.current_state() == SessionState::Running {
// this is to keep ticks between clients synchronized.
// if a client is ahead, it will run frames slightly slower to allow catching up
let mut fps_delta = 1. / FPS;
if sess.frames_ahead() > 0 {
fps_delta *= 1.1;
}
// get delta time from last iteration and accumulate it
let delta = Instant::now().duration_since(last_update);
accumulator = accumulator.saturating_add(delta);
last_update = Instant::now();
// if enough time is accumulated, we run a frame
while accumulator.as_secs_f64() > fps_delta {
// decrease accumulator
accumulator = accumulator.saturating_sub(Duration::from_secs_f64(fps_delta));
// add input for all local players
for handle in sess.local_player_handles() {
// obtain local input
sess.add_local_input(handle, get_local_input())?;
}
match sess.advance_frame() {
Ok(requests) => game.handle_requests(requests),
Err(GGRSError::PredictionThreshold) => {
println!("Frame {} skipped", sess.current_frame())
}
Err(e) => return Err(Box::new(e)),
}
}
}
// render the game state
render();
}