A stream that generates a 'tick' event every time the game state should update
()
| 378 | /// A stream that generates a 'tick' event every time the game state should update |
| 379 | /// |
| 380 | fn tick_stream() -> impl Send+Unpin+Stream<Item=VectorEvent> { |
| 381 | generator_stream(|yield_value| async move { |
| 382 | // Set up the clock |
| 383 | let start_time = Instant::now(); |
| 384 | let mut last_time = Duration::from_millis(0); |
| 385 | |
| 386 | // We limit to a certain number of ticks per callback (in case the task is suspended or stuck for a prolonged period of time) |
| 387 | let max_ticks_per_call = 5; |
| 388 | |
| 389 | // Ticks are generated 60 times a second |
| 390 | let tick_length = Duration::from_nanos(1_000_000_000 / 60); |
| 391 | |
| 392 | loop { |
| 393 | // Time that has elapsed since the last tick |
| 394 | let elapsed = start_time.elapsed() - last_time; |
| 395 | |
| 396 | // Time remaining |
| 397 | let mut remaining = elapsed; |
| 398 | let mut num_ticks = 0; |
| 399 | while remaining >= tick_length { |
| 400 | if num_ticks < max_ticks_per_call { |
| 401 | // Generate the tick |
| 402 | yield_value(VectorEvent::Tick).await; |
| 403 | num_ticks += 1; |
| 404 | } |
| 405 | |
| 406 | // Remove from the remaining time, and update the last tick time |
| 407 | remaining -= tick_length; |
| 408 | last_time += tick_length; |
| 409 | } |
| 410 | |
| 411 | // Wait for half a tick before generating more ticks |
| 412 | let next_time = tick_length - remaining; |
| 413 | let wait_time = Duration::min(tick_length / 2, next_time); |
| 414 | |
| 415 | Delay::new(wait_time).await; |
| 416 | } |
| 417 | }.boxed()) |
| 418 | } |