Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

“Run, sleeping when necessary” example doesn’t appear to sleep #1

Open
ticky opened this issue Feb 20, 2018 · 2 comments
Open

Comments

@ticky
Copy link

ticky commented Feb 20, 2018

Hi there!

From the examples in the docs:

Run a simulation at 30fps, sleeping if necessary to maintain the framerate:

use game_time::{GameClock, FrameCounter, FrameCount, FloatDuration};
use game_time::framerate::RunningAverageSampler;
use game_time::step;

let mut clock = GameClock::new();
let mut counter = FrameCounter::new(30.0, RunningAverageSampler::with_max_samples(60));
let end_time = FloatDuration::seconds(10.0);
let mut sim_time = clock.last_frame_time().clone();

while sim_time.total_game_time() < end_time {
   sim_time = clock.tick(&step::FixedStep::new(&counter));
   counter.tick(&sim_time);
   println!("Frame #{} at time={:?}", sim_time.frame_number(), sim_time.total_game_time());
}

Either the frame rate given by counter.average_frame_rate() is misreported, or this example does not in fact sleep as requested.

fn main() {
  use game_time::{FrameCount, FrameCounter, GameClock, FloatDuration};
  use game_time::framerate::RunningAverageSampler;

  let mut clock = GameClock::new();
  let mut counter = FrameCounter::new(30.0, RunningAverageSampler::with_max_samples(60));
  let end_time = FloatDuration::seconds(5.0);
  let mut sim_time = clock.last_frame_time().clone();

  while sim_time.total_game_time() < end_time {
      sim_time = clock.tick(&game_time::step::FixedStep::new(&counter));
      counter.tick(&sim_time);

      println!(
          "{:} wall, {:} game ({:.2}ms game, {:}fps game ({:.2}ms, {:.2}fps avg, slow: {}))",
          sim_time.total_wall_time(),
          sim_time.total_game_time(),
          sim_time.elapsed_game_time().as_milliseconds(),
          sim_time.instantaneous_frame_rate(),
          sim_time.elapsed_wall_time().as_milliseconds(),
          counter.average_frame_rate(),
          counter.is_running_slow(&sim_time),
      );

      std::thread::sleep(std::time::Duration::from_millis(5));
  }
}

This example runs in about 800ms of real time (wall time does indeed reflect this) but the sim_time.instantaneous_frame_rate() is a solid 30 despite the counter.average_frame_rate(). This seems to disprove that the example sleeps for the remainder of the target frame time.

Adding a call to sleep_remaining seems to result in more accurate world time, but lots of slow frames, and it doesn’t matter much whether I target 30 or 60 fps, it seems to be off by roughly 5%.

fn main() {
  use game_time::{FrameCount, FrameCounter, GameClock, FloatDuration};
  use game_time::framerate::RunningAverageSampler;

  let mut clock = GameClock::new();
  let mut counter = FrameCounter::new(60.0, RunningAverageSampler::with_max_samples(60));
  let end_time = FloatDuration::seconds(5.0);
  let mut sim_time = clock.last_frame_time().clone();

  while sim_time.total_game_time() < end_time {
      clock.sleep_remaining(&counter);
      sim_time = clock.tick(&game_time::step::FixedStep::new(&counter));
      counter.tick(&sim_time);

      println!(
          "{:} wall, {:} game ({:.2}ms game, {:}fps game ({:.2}ms, {:.2}fps avg, slow: {}))",
          sim_time.total_wall_time(),
          sim_time.total_game_time(),
          sim_time.elapsed_game_time().as_milliseconds(),
          sim_time.instantaneous_frame_rate(),
          sim_time.elapsed_wall_time().as_milliseconds(),
          counter.average_frame_rate(),
          counter.is_running_slow(&sim_time),
      );

      std::thread::sleep(std::time::Duration::from_millis(5));
  }
}

So my questions are:

  1. Is one of the tick calls intended to do the sleeping itself?
  2. If not, where is the sleep_remaining intended to go?
  3. Is there a way to sleep with less likelihood of missing your frame rate target?
@boozook
Copy link

boozook commented Apr 12, 2018

There is GameClock::sleep_remaining methods. You can use runner::FrameRunner helper (check out test / how to use it) or implement your own one like that.

@ticky
Copy link
Author

ticky commented Apr 13, 2018

Yeah, that’s fine, but the example I pointed to claims to “sleep if necessary” but does not actually do so!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants