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

Theme: auto

Setting Up the Game and Drawing

README.MD File

Your starting repo has a README.md file which contains placeholders for your name, email address, section, and platform. Edit this file to contain your information, and push this change to Github.

Code Setup

The starting code has a Main.cpp with a main function that does nothing and empty Game.h/Game.cpp files.

Create a new Game class in the Game.h/Game.cpp files. Create the following public functions (they will be empty or stubs for now):

  • A constructor
  • Initialize – No parameters and returns bool
  • Shutdown – No parameters and returns void
  • RunLoop – No parameters and returns void

We use separate Initialize/Shutdown functions rather than a constructor and destructor to have more control over the initialization and shutdown order of game systems.

Game::Initialize

This function initializes the game. It returns true if the game successfully initializes and false otherwise.

You will be using a lot of SDL functions in this lab, so include "SDL2/SDL.h" in Game.h.

For SDL functions, we will point you to examples in the documentation. You should look at the example, and adapt it as needed for our usage (this means you won’t necessarily directly copy/paste code from the documentation).

  1. Initialize SDL using SDL_Init: https://wiki.libsdl.org/SDL_Init. We need the audio and video subsystems.
  2. Create a window using SDL_CreateWindow: https://wiki.libsdl.org/SDL_CreateWindow. Make the window 1024 pixels wide and 768 pixels high. This function returns a SDL_Window*. Save this in a member variable in Game.
  3. Create a renderer using SDL_CreateRenderer: https://wiki.libsdl.org/SDL_CreateRenderer. We want to use the accelerated renderer and turn on VSYNC. To do this, pass in SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC as the third parameter to the function. This function returns an SDL_Renderer*. Save this in a member variable in Game.

If the window is too big to fit on your screen, what you can do is instead pass in half the width/height to SDL_CreateWindow (so 512x384) but then use SDL_RenderSetLogicalSize and set the logical size to the normal 1024x768. That way your window will be half the size but the coordinates of everything will still be the full size.

Game::RunLoop

This function runs the game loop.

This is where you will implement the “game loop” as discussed in lecture. Recall that each iteration of the game loop has three phases: process inputs, update game, generate outputs. Make member functions for each of these three phases (ProcessInput, UpdateGame, GenerateOutput) – make them empty for now.

Now implement an infinite loop in RunLoop, calling the functions you just created for the three phases (in the correct order).

In SDL, you may receive events that the game must respond to. So, in your ProcessInput function, use SDL_PollEvent to poll for available events: https://wiki.libsdl.org/SDL_PollEvent. Note that there could be more than one event per frame, which is why the example uses while (SDL_PollEvent…). You should mimic this in your ProcessInput function. For now, we won’t do anything with the events we get from SDL_PollEvent (this will change soon).

We will add code to UpdateGame and GenerateOutput in a bit.

Game::Shutdown

This function shuts down SDL systems (and anything else needed).

This function simply needs to:

  1. Destroy the renderer – https://wiki.libsdl.org/SDL_DestroyRenderer
  2. Destroy the window – https://wiki.libsdl.org/SDL_DestroyWindow
  3. Quit SDL – https://wiki.libsdl.org/SDL_Quit

To test your Game class, create an instance of Game in Main.cpp. Then call Initialize. If Initialize returns true, call RunLoop (you don’t want to run if you failed to initialize). Then call Shutdown (you should call Shutdown regardless if initialize succeeds or fails).

When you run your game, you should see an empty window of the correct size. The inside of the window will be black, white, or grey.

There is currently no way to quit the game, other than stopping it in the debugger.

SDL_QUIT

Let’s add support for quitting. There are multiple ways to quit (close the window, use the quit shortcut key, or press ESC). Change your game loop so that the condition is a bool member variable. This allows you to stop the loop by setting the bool to false.

Next, update the loop in ProcessInput to check if any of the events are of type SDL_QUIT.

The SDL_Event documentation describes how to test the type of an SDL event: https://wiki.libsdl.org/SDL_Event#reading.

In our case, instead of SDL_MOUSEMOTION, we are testing for an SDL_QUIT event: https://wiki.libsdl.org/SDL_EventType#SDL_QUIT. If you detect an event of type SDL_QUIT, set your game loop bool to false (so the loop exits).

Now when you run the game, it should quit if you click the “X” button on the window.

Simple Keyboard Input

While we could also use events for keys, it’s often easier to grab the state of the entire keyboard and test the status of individual keys.

So, after the entire SDL_PollEvent loop in ProcessInput, call SDL_GetKeyboardState: https://wiki.libsdl.org/SDL_GetKeyboardState. Then, check the state for whether the ESC key is pressed. If so, set your game loop bool to false. (This list of scan codes is here: https://wiki.libsdl.org/SDL_Scancode).

Now when you run the game, it should also quit if you press the ESC key.

Drawing

SDL rendering uses a back buffer (which we’ll cover later in the semester). For now, just know that every frame, the game code must clear the back buffer, draw the scene, and “present” the back buffer.

In GenerateOutput, do the following:

  1. Set the render draw color to blue (0, 0, 255, 255) using SDL_SetRenderDrawColor: https://wiki.libsdl.org/SDL_SetRenderDrawColor
  2. Clear the backbuffer using SDL_RenderClear: https://wiki.libsdl.org/SDL_RenderClear
  3. Draw your game objects (which we will do in a second)
  4. Present using SDL_RenderPresent: https://wiki.libsdl.org/SDL_RenderPresent

Now your window should be filled in blue: Blue window

Walls

Now let’s draw game objects. Remember that all game objects should be drawn after the SDL_RenderClear call but before the SDL_RenderPresent call.

First, add three white walls on the top, right, and bottom of the screen. To do this, set the color to white (all 255s) using the same SDL_SetRenderDrawColor function. Then draw the walls as rectangles using SDL_RenderFillRect: https://wiki.libsdl.org/SDL_RenderFillRect.

Remember that in the SDL coordinate system, (0, 0) is the top left corner of the window.

Hint: Make a constant for the thickness of the walls, so that it’s easy to adjust and avoids using magic numbers throughout your code.

You should now have walls that look something like this: Walls

Paddle

On the left part of the screen, add a paddle (this is what the player will use to hit the ball). Instead of hard coding the position of the paddle like the wall, create a SDL_Point member variable for the paddle’s position. (Of course, you need to initialize the variable).

When you draw the paddle, draw it centered around its position. This will make it easier to draw the paddle in the correct spot once you start updating the position later in this lab. Hint: Make a constant for the height of the paddle.

You should now have a paddle on the screen (you can use whichever color you want, I stuck with white): Paddle

Ball

Since SDL doesn’t have a draw circle function, we’ll just use a square for the ball (this is how it’s implemented in the original Pong). As with the paddle, create an SDL_Point member variable for the ball position. Initialize the position of the ball to the center of the window.

You should now have a ball (though it doesn’t move): Ball

This is the end of part 1.

Commit and push your code. Verify that you can view your code on the GitHub website!

Once you’ve pushed this code, you’re ready to move on to part 2.