Skip to main content Link Search Menu Expand Document (external link)

Theme: auto

Delta Time and Movement

Before you can move the paddle or ball, you first need to compute the delta time. Remember that delta time is the difference between the current frame’s time and the previous frame’s time. You compute this delta time in UpdateGame, before updating game objects.

Calculating Delta Time

The SDL_GetTicks function returns the number of milliseconds (ms) elapsed since the game initialized SDL: https://wiki.libsdl.org/SDL3/SDL_GetTicks. In UpdateGame, use SDL_GetTicks to get the current time, and the difference between this and the previous frame’s time is the delta time. You’ll have to store this “previous” time in a Uint64 member variable, which you should initialize to 0.

After computing the difference in time, convert the milliseconds to seconds (as a float), and save it in a local deltaTime variable. Remember that there’s 1,000 milliseconds in every second.

We convert the milliseconds to seconds simply because it’s easier to perceive and think about time in seconds. Eg. “I want the enemy to take 5 seconds to move there” is just easier to say than “in 5000 milliseconds”.

Because we told SDL that we want an update rate of approximately 60 times a second, it means your delta time should be 0.016-0.017 every frame. You can roughly validate this by using an SDL_Log statement:

SDL_Log("%f", deltaTime);

When you run, you’ll see lots of spam on the debug pane at the bottom of CLion. Once you confirm you’re getting the 0.016-0.017, delete the SDL_Log line, because we don’t want it to just spam.

SDL_Log uses a printf-style syntax for formatting. You may not be familiar with this as it’s more a C thing instead of C++. The first parameter to the function is a string literal which can contain variable placeholders that begin with % and are followed by a letter for the type. The number of additional parameters to the function should equal the number of variable placeholders. For example, this would print a float, an integer, and a C-style string:
SDL_Log("My float is %f, int is %d, and %s", 5.0f, 10, "Hello!");

Capping to Maximum Delta Time

Although it may seem like the delta time calculation works properly, there is one problem.

To see it in action, put a breakpoint on your line that calculates deltaTime and run the game. If you step over the line, what do you get as your deltaTime? For me, I get about 1.3 seconds, which is a huge deltaTime that we don’t want as it would make things move a lot on the first frame.

You can sort of fix this issue by updating your “previous” time variable in Initialize, after LoadData. You should then end up with a deltaTime close to 0 (if not exactly 0) on the very first frame.

But this still doesn’t quite work, after the first frame, if you hit continue and hit the breakpoint again, you’ll see that your deltaTime is really big again. This is because the time spent paused in the debugger still counts towards the SDL ticks time!

So, to prevent this issue, after calculating deltaTime, cap it so it can’t be higher than 0.033f (you could use Math::Min for this). This is saying, “If it took more than 0.033 seconds (33 ms) last frame, just pretend like it only took 33 ms.”

Now if you use breakpoints, you should be able to confirm that if you calculate a deltaTime higher than 0.033, the deltaTime changes to 0.033.

Moving the Paddle

The player should be able to hold down the A key to move the paddle left and hold down the D key to move the paddle right. A rough approach to this is:

  1. In ProcessInput, check the state of the keys, and save the direction you should move in (if any) in a member variable
  2. At the bottom of UpdateGame, use your delta time and move the paddle as a function of delta time, based on the member variable from (1)
  3. Make sure it’s not possible for the player to move the paddle off the screen (one way to do this is to always run the code in (2) and then fix the position afterwards if needed)

Do not attempt to move the paddle in ProcessInput. In order to move the paddle at the correct speed regardless of the frame rate, you need delta time, and delta time is only available to UpdateGame.

You should now be able to move the paddle left and right (and not off screen). Make sure that if you let go of both the A and D keys, the paddle doesn’t move: Paddle moving

Ball Movement

First, add an Vector2 member variable for the ball’s velocity (and initialize it to something so the ball moves diagonally and upwards at the start).

Every frame, the ball’s new position is the old position plus the velocity times delta time.

The ball should now move based on your velocity, though it will fly off the screen since we’ve not implemented bouncing yet.

Ball Bouncing

Since we added a function to Transform to calculate a SDL_FRect for each actor, we can take advantage of one of SDL’s other functions to detect intersections between the ball and the other actors, SDL_HasRectIntersectionFloat: https://wiki.libsdl.org/SDL3/SDL_HasRectIntersectionFloat.

So, after you move the ball, check for intersections between the ball’s rectangle and the other actor’s rectangle. You’ll need to negate the appropriate component of the ball’s velocity based on what you hit (x for left/right and y for top/paddle).

To make sure the ball can’t get stuck on a wall or the paddle, you should only negate the velocity component if the ball is moving towards that wall/paddle. For example, if the ball is moving towards the left wall, and intersects the left wall, you should negate the x component. However, if the ball is actually moving away from the left wall, you don’t want to negate the component because the ball is trying to escape. Negating it again would just make it move towards the left wall again, which isn’t correct.

Your game should now play roughly like the reference version, which you can play here. You may have different colors and different speeds, but it should still play approximately like that.

Losing the Game

Finally, add code that checks if the ball has gone off the screen to the bottom (meaning the player missed the ball). If this happens, set your “continue running” bool to false.

Confirm that if the ball flies off the screen, the game closes.

This concludes Lab 1. Make sure you push your completed code to GitHub, and verify that you successfully pushed by viewing your code on the GitHub website. You should also confirm that your GitHub actions successfully finished and, for an A, fix your warnings. You can view information about how to see your GitHub actions are fairing here.

Once you’ve pushed your code, you should review the grading specifications to confirm you’ve satisfied them.