• 2D shoot 'em up
The Legend of Edgar 1.37
SDL2 Santa game tutorial 🎅
SDL2 Shooter 3 tutorial
The Legend of Edgar 1.36
SDL2 map editor tutorial [UPDATED]
— 2D Santa game —
We've been staring at an non-interactive scene for the past few parts, so it's time for Santa himself to make an appearance. In our game, Santa will be piloting his sleigh solo, and with the need to keep it aloft by using W to gain height.
Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./santa04 to run the code. You will see a window open like the one above, with the scene moving from right to left. To steer Santa's sleigh, using the WASD control scheme, to move up, left, down, and right. Santa will be constrained to an area of the screen, and cannot crash into anything (including the ground). Gravity will continue to drag the sleigh down. When you're finished, close the window to exit.
Inspecting the code
So, what's going on? Why are there no reindeer? Well, our story is that it's Christmas Eve and sadly all 9 of Santa's reindeer are laid up in bed with a stomach bug, after eating some dodgy sprouts. It's therefore up to Santa alone to save Christmas. His sleigh is still magic, but can't quite sustain itself fully without all of his reliable caribou buddies. Not only that, but in his haste to get things going, Santa has departed the North Pole without a full stock of gifts and coal. Not to worry, his trusty elves have used their magic to teleport the toys and rocks to him. Unfortunately, the elves' magic isn't without its problems, and so it's also brought a bunch of snowmen to life, who are now focused on ruining the night for everyone.
Hey, it's a good enough explaination, right? Right? Anyway, moving on ...
As we can see once more, this part is short and sweet, and quite easy to understand. The base code that we've built up over this series of tutorials enables us to get going quite quickly, and our established code patterns make swift work of adding in new things.
Starting first with defs.h:
We now have an ET_PLAYER entity enum.
Over to structs.h:
We've added a pointer to the player in Stage. While this isn't being used right away, it will become useful later on when we need to find out things about the player's entity.
Now over to player.c, a new compilation unit that will handle all the player's logic and rendering. One shouldn't expect anything tricky at this point. Starting with initPlayer:
Other than loading our required textures and setting the essentials, there's not much to be said about the creation of the player Entity. Two things of note are that the player's `dy` is set to -8, so that the seligh doesn't immediately fall from the sky when the game starts. Also of note is that we're setting Stage's `player` entity pointer to the entity we've created here (`e`).
Moving over to the `tick` function next:
Here, we're doing just one thing, calling a function named `move`:
The `move` function is concerned with moving the sleigh, as well as constraining it to an area of the screen. We start by increasing the value of the sleigh entity's (`self`) `dy`, as a means of applying gravity to the sleigh, and then set a control variable called `dx` to 0. Next, we test if any of the keys in the WASD control scheme have been pressed. If so, we'll move the sleigh as appropriate. Pressing A or D will move the sleigh left and right (by setting the value of `dx`), while pressing W or S will adjust the value of the entity's `dy`.
For both the sleigh's `dx` and `dy`, we're accelerating on the horizontal and vertical. Notice how if we don't press A or D that the sleigh comes to a complete stop. We determine this by testing the control variable `dx`, to see if there was any movment to be applied. We limit the values of the sleigh's `dx` and `dy` values to between -5 and 5, before adding them to the sleigh's `x` and `y`, to stop the sleigh from moving too fast.
To constrain the position of the sleigh, we take a couple of different approaches. For the horizontal, we limit its `x` value to 10 pixels on the left and right of the screen. The vertical is handled differently, depending on whether we are at the top or bottom of the screen. If we reach the top of the screen, we limit the sleigh to 50 pixels on the vertical and also set its `dy` to 0. This means that the sleigh will immediately fall if we release W. For the bottom, we don't allow the sleigh to be lower down than its runners on the ground (so, the position of the ground, less the height of the sleigh's texture). Again, we set `dy` to 0, so that the sleigh can lift off again immediately, without having to fully reverse the value of `dy`.
So, in summary, we're using the WASD control scheme to steer the sleigh, with gravity being applied each frame.
Notice how the player entity isn't affected by the speed of the stage. For all intents and purposes, the player is static on the screen, while everything else moves around it. If we applied the stage's speed to the player, they would move off screen like everything else, and we don't want that.
On to the `draw` function next:
Nothing special going on here. We're just rendering the sleigh, using its texture.
Finally, the loadTexture function:
We're loading just one texture right now - sleighTexture. We'll be loading more the future, and this function will serve us well when we come to do so.
That's all there is to player.c for now. We only need to do one more thing to enable our player, so it's over to stage.c, where we're updating initStage:
Adding in initPlayer here will cause our player entity to be created, allowing the sleigh to be controlled and drawn on our stage.
And that's it. We now have the houses, chimneys, and Santa's sleigh. There are a number of other things that still need to be added, but we're making excellent progress. What we should add in next is the ability to deploy gifts and coal. This is Santa's job, after all. So, in the next part we'll introduce these two things.
The source code for all parts of this tutorial (including assets) is available for purchase, as part of the SDL2 tutorials bundle: