Skip to content

19. Handling Time

Learn how to manage time using "elapsed time from the previous frame."

19.1 Measuring Elapsed Time

  • Scene::DeltaTime returns the elapsed time from the previous frame (in seconds) as a double type
  • By accumulating this elapsed time, you can measure the elapsed time (in seconds) since the program started

# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	const Font font{ FontMethod::MSDF, 48 };

	// Elapsed time since program start (seconds)
	double time = 0.0;

	while (System::Update())
	{
		// Elapsed time from previous frame (seconds)
		const double deltaTime = Scene::DeltaTime();

		// Add deltaTime to time
		time += deltaTime;

		// Display time
		font(U"time: {:.2f}"_fmt(time)).draw(40, Vec2{ 40, 40 }, ColorF{ 0.1 });

		// Display deltaTime
		font(U"deltaTime: {:.4f}"_fmt(deltaTime)).draw(40, Vec2{ 40, 100 }, ColorF{ 0.1 });
	}
}
  • The convenient Stopwatch class for measuring elapsed time will be explained in detail in Tutorial 30

19.2 Countdown Timer

  • Apply 19.1 to create a program that counts down remaining time from 10 seconds
  • When the remaining time reaches 0, display "Time's up!"
  • Pressing Enter resets the remaining time and starts the countdown again

10-second countdown
# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	const Font font{ FontMethod::MSDF, 48 };

	// Countdown time (seconds)
	const double countdownTime = 10.0;

	// Remaining time (seconds)
	double remainingTime = countdownTime;

	while (System::Update())
	{
		// Elapsed time from previous frame (seconds)
		const double deltaTime = Scene::DeltaTime();

		// Reduce remaining time
		remainingTime -= deltaTime;

		if (0.0 < remainingTime) // If there's remaining time
		{
			font(U"time: {:.2f}"_fmt(remainingTime)).draw(40, Vec2{ 40, 40 }, ColorF{ 0.1 });
		}
		else // If time is up
		{
			font(U"Time's up!").draw(40, Vec2{ 40, 40 }, ColorF{ 0.1 });
			font(U"Press Enter to restart").draw(30, Vec2{ 40, 100 }, ColorF{ 0.1 });

			// If Enter key is pressed
			if (KeyEnter.down())
			{
				// Reset remaining time and restart
				remainingTime = countdownTime;
			}
		}
	}
}
  • The convenient Timer class for countdown timers will be explained in detail in Tutorial 30

19.3 Doing Something at Regular Intervals (1)

  • Create a program that accumulates time and does something when a certain amount of time has accumulated
  • Decide on an event period and trigger an event when accumulated time (seconds) exceeds that period (seconds)
  • After triggering an event, subtract that period from the accumulated time
  • The following code increases the level every 2 seconds

Increase level every 2 seconds
# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	const Font font{ FontMethod::MSDF, 48 };

	// Level up interval (seconds)
	const double levelUpInterval = 2.0;

	// Accumulated time (seconds)
	double accumulatedTime = 0.0;

	// Level
	int32 level = 0;

	while (System::Update())
	{
		// Elapsed time from previous frame (seconds)
		const double deltaTime = Scene::DeltaTime();

		// Increase accumulated time
		accumulatedTime += deltaTime;

		// If accumulated time exceeds the interval
		if (levelUpInterval < accumulatedTime)
		{
			// Increase level
			++level;

			// Reduce accumulated time by the interval amount
			accumulatedTime -= levelUpInterval;

			Print << U"Level up!";
		}

		// Display current level
		font(U"Level: {}"_fmt(level)).draw(40, Vec2{ 200, 40 }, ColorF{ 0.1 });

		// Display accumulated time
		font(U"accumulatedTime: {:.2f}"_fmt(accumulatedTime)).draw(30, Vec2{ 200, 100 }, ColorF{ 0.1 });
	}
}

19.4 Doing Something at Regular Intervals (2)

  • In 19.3, you had to wait until the first event occurred after starting the program
  • If you want the first event to occur immediately after startup, set the initial value of accumulated time to the same value as the period
  • The following code increases the number of enemies immediately at the start and then every 2 seconds thereafter

Increase enemy count immediately at start and every 2 seconds thereafter
# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	const Font font{ FontMethod::MSDF, 48 };

	// Enemy increase interval (seconds)
	const double levelUpInterval = 2.0;

	// Accumulated time (seconds)
	double accumulatedTime = levelUpInterval;

	// Number of enemies
	int32 enemyCount = 0;

	while (System::Update())
	{
		// Elapsed time from previous frame (seconds)
		const double deltaTime = Scene::DeltaTime();

		// Increase accumulated time
		accumulatedTime += deltaTime;

		// If accumulated time exceeds the interval
		if (levelUpInterval < accumulatedTime)
		{
			// Increase number of enemies
			++enemyCount;

			// Reduce accumulated time by the interval amount
			accumulatedTime -= levelUpInterval;

			Print << U"Enemy appeared!";
		}

		// Display current number of enemies
		font(U"Enemy count:	{}"_fmt(enemyCount)).draw(40, Vec2{ 200, 40 }, ColorF{ 0.1 });

		// Display accumulated time
		font(U"accumulatedTime: {:.2f}"_fmt(accumulatedTime)).draw(30, Vec2{ 200, 100 }, ColorF{ 0.1 });
	}
}

Review Checklist

  • Learned that Scene::DeltaTime returns the elapsed time from the previous frame (in seconds) as a double type
  • Learned that elapsed time (in seconds) can be measured by accumulating elapsed time
  • Learned how to create a countdown timer for remaining time
  • Learned how to do something at regular intervals