Tick Rate and Time Deltas

Alternatives to SDL_Delay()

What are some alternatives to SDL_Delay() for more precise timing control?

Abstract art representing computer programming

While SDL_Delay() is a simple way to introduce pauses in your game loop, it's not always the most precise or efficient method for timing control. Here are some alternatives that can provide more accurate timing:

SDL_AddTimer()

SDL provides a timer mechanism that can call a callback function at specified intervals. This can be more precise than SDL_Delay():

#include <SDL.h>
#include <iostream>

Uint32 timerCallback(Uint32 interval,
                     void* param) {
  std::cout << "Timer fired at " <<
    SDL_GetTicks64() << " ms\n";
  // Return the same interval to
  // keep the timer going
  return interval;
}

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_TIMER);

  SDL_TimerID timerId = SDL_AddTimer(
    100, timerCallback, nullptr);

  // Main loop
  for (int i = 0; i < 50; ++i) {
    // Just to keep the program running
    SDL_Delay(10);
  }

  SDL_RemoveTimer(timerId);
  SDL_Quit();
  return 0;
}
Timer fired at 100 ms
Timer fired at 200 ms
Timer fired at 300 ms
Timer fired at 400 ms
Timer fired at 500 ms
...

This approach allows you to perform actions at regular intervals without blocking the main thread.

High Resolution Timer

For more precise timing, you can use SDL's high resolution timer functions:

#include <SDL.h>
#include <iostream>

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_TIMER);

  Uint64 performanceFrequency =
    SDL_GetPerformanceFrequency();
  Uint64 start = SDL_GetPerformanceCounter();

  // Simulate some work
  for (int i = 0; i < 1000; ++i) {
    std::cout << "Working...\n";
  }

  Uint64 end = SDL_GetPerformanceCounter();
  double elapsed = (end - start) / static_cast<
    double>(performanceFrequency);

  std::cout << "Elapsed time: " << elapsed <<
    " seconds\n";

  SDL_Quit();
  return 0;
}
...
Working...
Working...
Elapsed time: 0.0356943 seconds

This method provides nanosecond precision, which is much more accurate than SDL_GetTicks64().

Busy Waiting

For extremely precise timing, you can use a busy-wait loop. However, this approach uses 100% CPU while waiting:

#include <SDL.h>
#include <iostream>

void preciseSleep(double seconds) {
  Uint64 performanceFrequency =
    SDL_GetPerformanceFrequency();
  Uint64 start = SDL_GetPerformanceCounter();

  while (true) {
    Uint64 now = SDL_GetPerformanceCounter();
    double elapsed = (now - start) / static_cast
      <double>(performanceFrequency);
    if (elapsed >= seconds) { break; }
  }
}

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_TIMER);

  std::cout << "Starting at " <<
    SDL_GetTicks64() << " ms\n";
  preciseSleep(0.1); // Sleep for 0.1 seconds
  std::cout << "Ended at " << SDL_GetTicks64()
    << " ms\n";

  SDL_Quit();
  return 0;
}
Starting at 0 ms
Ended at 100 ms

This method provides very precise timing but at the cost of high CPU usage.

std::chrono

C++'s standard library provides the <chrono> header, which offers high-precision timing facilities:

#include <SDL.h>
#include <chrono>
#include <iostream>
#include <thread>

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_TIMER);

  auto start =
    std::chrono::high_resolution_clock::now();

  // Sleep for 100 milliseconds
  std::this_thread::sleep_for(
    std::chrono::milliseconds(100));

  auto end =
    std::chrono::high_resolution_clock::now();
  std::chrono::duration<double> elapsed = end -
    start;

  std::cout << "Elapsed time: " << elapsed.
    count() << " seconds\n";

  SDL_Quit();
  return 0;
}
Elapsed time: 0.100734 seconds

This method combines high precision with the ability to sleep without consuming CPU resources.

When choosing an alternative to SDL_Delay(), consider the trade-offs between precision, CPU usage, and complexity. For most games, a combination of SDL_AddTimer() for regular updates and std::chrono for precise measurements often provides a good balance of accuracy and efficiency.

This Question is from the Lesson:

Tick Rate and Time Deltas

Learn how to create smooth, time-aware game loops that behave consistently across different hardware configurations

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Tick Rate and Time Deltas

Learn how to create smooth, time-aware game loops that behave consistently across different hardware configurations

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 67 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved