SDL2 Shooter 2 tutorial
SDL2 Widget tutorial
SDL2 Adventure tutorial
Orb source code
— 2D Shoot 'Em Up Tutorial —
Note: this tutorial builds upon the ones that came before it. If you aren't familiar with the previous tutorials in this series you should read those first.
In the first tutorial, we learned how to open a window in SDL2. We're now ready to do something a little more interesting: moving the player. Unpack the code and then type make to build. Once compiling is finished type ./shooter03 to run the code.
A 1280 x 720 window will open, coloured a light shade of blue. A spaceship sprite will also be shown, as in the screenshot above. The ship can now be moved using the arrow keys. Up, down, left, and right will move the ship in the respective directions. Close the window by clicking on the window's close button.
Inspecting the code
There have been a number of changes to the code to allow us to move the player about the screen. Let's start with structs.h.
We've added four new integers: up, down, left, and right. These variables will track our movement requests. When we push the arrow keys on the keyboard we'll set the relevant variable value. In order to facilitate this, we need to make a few changes and additions to input.c:
The first change is that we've now added two additional case statements to handle new SDL event types - one to handle SDL_KEYDOWN and the other to handle SDL_KEYUP. These two event types will occur whenever a key on the keyboard is pushed down and whenever one is released. The doKeyDown or doKeyUp functions will be called whenever this happens, passing the SDL_KeyboardEvent that triggered this along. Let's look at the doKeyDown function.
Glacing at this, we can see that we're testing the scancode of the keyboard event to see which key it was (there are A LOT of scan codes available. A full list can be found here: https://wiki.libsdl.org/SDL_Scancode). Whenever we detect an SDL_SCANCODE_UP scancode, we set the app.up variable to 1. app.down, app.left, and app.right will be set as per the SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, and SDL_SCANCODE_RIGHT scancodes. That should be quite easy to understand. One thing we have done is tested to see whether or not the keyboard event that was sent was a result of a keyboard repeat event (event->repeat). In the main, we want to ignore keyboard repeat events; these could queue up and cause some unexpected things to happen, and so we only want to deal with events where the key has been pushed down for the first time. Now let's look at doKeyUp:
As you can see, it's pretty much the same as doKeyDown, except that we're now setting the app.up, etc. variables to 0. Finally, let's turn to main.c where we'll be dealing with the player movement.
As you can see, we've added a few tests of the app.up et al. variables. When these are set to 1, the player x and y will be updated. app.up and app.down will add and subtract 4 from the player y coordinate. app.left and app.right will do the same to the player x coordinate.
Now, at this point you're probably wondering why we're using these app.up etc. variables, instead of moving the player in the doKeyDown function in input.c. The answer to this is simple: those events fire only once when the key is pushed down (or a few more times if we're considering repeat events). This means that in order to move the player the arrow keys would need to be tapped constantly to make the ship cross the screen; keyboard repeat events are even worse in this case, as it leads to jerky movement all over the place. This isn't what we want. Setting the app.up family to 1 when a key is pushed down and 0 when the key is released means that the relevant key need only be held down to keep the player moving and released when we want the player to stop.
We've ticked off a few essentials on our road to creating a shooter - we can draw graphics and we can respond to player input. The next step will be to add the ability to fire bullets so that the player can defend themselves from the waves of enemies we will also soon add.
The source code for all parts of this tutorial (including assets) is available here:
It is also available as part of the SDL2 tutorial bundle (with on-going updates):