# Creating a variable delta time javascript game loop

- 5 mins
Hello1

## Variable delta time game loop

In this tutorial we are going to learn how to make our game and square speed not be effected when the game loop is running faster than normal.

In the first tutorial we created two game loops to simulate a game being played on two different computers, where one computer's performance and frame rate was double the other. This was simulated by calling the game loop associated with the `faster computer` twice as often. We saw that the player with the more performant computer moved twice as fast across the screen as the other player.

This is an unfair advantage that any multiplayer game needs to counteract to even the playing field. Even for one player games if we become used to certain timing for a game that we can rely on for certain animations or moves to take to complete and suddenly they are taking even 5% shorter or longer this will be noticeable and in any game that relies on fast reaction's such as a fighting game this randomness will be make the game frustrating to play.

## What is delta time

The problem that we have is that the game's speed is determined by it's frame rate (different for different hardware) instead of the time that has elapsed (the same per player). In fact if we move a square 10 units to the right every time a frame ticks over that players speed is not 10 units / second.

Most games will run at about 60 frame per second so actually that square is moving at `60*10 = 600` pixels per second! We can also see that as the frame rate changes the new speed changes which is the effect we saw in the first tutorial.

So we have two problems

• Hardware performance effects game play
• Our measurements are not predictable so we can't set a desired speed such as 10 pixels per second.

The concept of `delta time` can help to solve both of these problems by helping us to create a variable game loop.

Up until now how much of the game we simulate per frame has remained constant, so when the game is running fast we simulate more game state changes, speeding up the game and the opposite is true.

If we assume that our game should be running at `60fps` then 1 frame occurs every `1/60 = 0.01666667` seconds, this ratio can be set to a variable called `deltaTime`. If we multiple all of our physics calculations by `deltaTime` we will ensure that our player is not moving `600 units / second` but instead `10 units / second` as shown in the example below.

``````playerSpeed = 10
playerXPosition = 0
deltaTime = 1/60.0
//new frame occurs
new playerXPosition = playerXPosition + playerSpeed * deltaTime
//playerXPosition = 0 + 10 * (1/60) = 0.1666667 = how many units the player moves / frame
//In 60 frames the player moves =  0.1666667 * 60 = 10 units / 60 frames = 10 units / second as desired
``````

As shown above `deltaTime` allows us to negate the effect of a frame occurring every 1/60th of a second. Now this will work in a perfect world when our game is running at 60 frame per second but as we know the frame rate can vary and so this is why we should use a variable `deltaTime`.

This may lead us to the question, what should we set our `deltaTime` variable to each game loop? Well the answer is in the name `deltaTime` just refers to the change in time that has occurred so we can determine the `deltaTime` each game loop by storing the time the previous game loop occurred and taking the different between the `current time` and the previous game loop time.

Next we will see all of this theory in action as we implement the same process and introduce a variable delta time game loop into our game loop in the following section.

## Adding a variable delta time game loop

First step is to start using both game loops again so that we can compare them. Make the following changes to the code.

Comment the intervalWorker code in GameRuntime.

``````//let intervalWorker = new Worker('web-worker.js');
//intervalWorker.onmessage = GameRuntime.loop
``````

Uncomment game loop1

``````const game1UpdateLoopsPerSecond = 1000 / 60
setInterval(GameRuntime.loop, game1UpdateLoopsPerSecond)
``````

Uncomment game loop 2

``````const game2UpdateLoopsPerSecond = 1000 / 30
setInterval(GameRuntime.loop2, game2UpdateLoopsPerSecond)
``````

Now run the app and confirm both squares move side to side across the screen and that the second square is moving half the speed of the first.

## Introduce engine state to game state

We want to capture the time the game `started` as well as the time during the previous loop for each game loop so that we can calculate how much time has passed (deltaTime). We can store this in a metadata game state object relating to our game engine and game loop. Lets create two fields on `GameState` called `engine1` and `engine2` that will hold the `startTime` and `timePreviousLoop`. The `engine` property will represent the game engine meta data for each game loop. Make the changes to `types.ts` by adding the following fields to `GameState` as below.

``````engine1: {
timePreviousLoop: number,
startTime: number
},
engine2: {
timePreviousLoop: number,
startTime: number
}
``````

Next update the `InitialGameState` in `GameConstants.ts` to include the new `engine` property as below.

``````engine1: {
timePreviousLoop: 0,
startTime: 0
},
engine2: {
timePreviousLoop: 0,
startTime: 0
}
``````

## Use timePreviousLoop to calculate variable deltaTime

The startTime should be set when the game begins. In `GameRuntime`'s setup method add the following code below the `GameRuntime.context` declaration.

``````const now = Date.now();
GameRuntime.gameState.engine1.startTime = now;
GameRuntime.gameState.engine1.timePreviousLoop = GameRuntime.gameState.engine1.startTime;
GameRuntime.gameState.engine2.startTime = now;
GameRuntime.gameState.engine2.timePreviousLoop = GameRuntime.gameState.engine2.startTime;
``````

Now we will use the `timePreviousLoop` to calculate `deltaTime` for game loop 1.

In the `updateGameState` method in `GameRuntime.ts` add the following to the top of the method.

``````const currentTime = Date.now()
const deltaTimeMillis = currentTime - gameState.engine1.timePreviousLoop
const deltaTimeSecs = deltaTimeMillis / 1000.0
GameRuntime.gameState.engine1.timePreviousLoop = currentTime;
``````

First we determine the current time, this is an epoch time which returns the number of milliseconds since `Jan 1970 UTC`. Next we determine how many milliseconds have elapsed since the current time and the previous loop time. Finally we convert this to be in terms of seconds not milliseconds which will allow us to use it as a multiplier in all of our `physics` calculations that require things to move a certain amount of units / second. We also need to update the `timePreviousLoop` to the current time.

Lets use `deltaTimeSecs` where we calculate the `square1X`, replace the old line with the new line below.

``````const square1X = gameState.squares.square1.pos.x + (square1Velocity * deltaTimeSecs)
``````

Restart the app and check to see the result. Huh, is that first square even moving, if you stare at the screen long enough it's clear that it is, but why soo slow? well now that we are multiplying `deltaTimeSecs` our player has been slowed down as `deltaTime` is currently set to `1/60 = 0.016666667` seconds.

Before using `deltaTime` we set our `velocity` to 1 as anything faster meant our square was moving too fast. Now we are transforming player 1's position based on time we can set our velocity to whatever units per second we want. Try `80` by changing the value in the `InitialGameState` as below.

``````x: 80
``````

Run the app again and checkout the result. You might be wondering why did I pick `80`, well the canvas width is `800` so now we can check, count how long it takes player 1 square to move from one side of the canvas to the other. It should take 10 seconds as we are moving 80 units / second and the canvas is 800 units wide.

Hopefully you can see how having predictable speeds will help when designing a game and making in game decisions.

## Update player 2 to use deltaTime

To update game loop 2 to use deltaTime we can follow a very similar process as we did for game loop 1 but instead update the `loop2` method. I will leave this as a challenge for the reader but if you get stuck remember you can see the finished code above.

Once you have finished set player 2's velocity to `80` and run the app to see the results, what do you observe? If you paid close attention to the beginning of the tutorial you may notice that the squares are more consistent with their set speeds than before. Even when player 2 was moving at half the pace of player 1 if you run the app for long enough you might notice that player 1 was already bouncing the starting wall before player 2 got to the right wall ie it was covering more than 2 time the distance. This is probably due to a rounding error that gets magnified over time. By multiplying our calculations by deltaTime we are reducing the magnitude of this error.

What you should also notice is now the two squares are moving at the same speed despite game loop 1 being called twice as much as game loop 2. This is simulating a faster and slower computer and shows that both players can have the same experience regardless of hardware.

Problem solved... or is it? Did you notice how the squares can eventually become stuck around the edges of the screen and get out of sync with each other?

Unfortunately (or fortunately if you are enjoying this course) our game loop design journey does not step here. There is a good reason for why this is happening and we will look to resolve it in the next tutorial.