• 2D shoot 'em up
SDL2 Santa game tutorial 🎅
SDL2 Shooter 3 tutorial
The Legend of Edgar 1.36
SDL2 map editor tutorial [UPDATED]
TBFTSS: The Pandoran War - Amiga OS4 Port
— Mission-based 2D shoot 'em up —
Before we move onto implementing missions and objectives, we should take the opportunity to work on our secondary weapons. We will have 4 weapons and a shield system in the end, all which will have unique properites. We're going to start with a simple one: rockets.
Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./shooter3-07 to run the code. You will see a window open like the one above. Use the WASD control scheme to move the fighter around. Hold J to fire your main guns. Press I to fire your secondary weapon (rockets). Play the game as normal. Firing a rocket will consume ammo. Collect more ammo power-ups from defeated enemies to replenish your stock. Once you're finished, close the window to exit.
Inspecting the code
Adding in our rockets is very, very easy. Rockets are basically bullets, with high damage, and a different `tick` function to that which we already have.
We'll start with the update to defs.h:
We've created a new enum to represent our secondary weapon (SW being short for Secondary Weapon). SW_NONE will mean we don't have a secondary weapon, while SW_ROCKET will declare we have rockets.
Now on to structs.h:
We've updated Game's `kite`'s struct, adding in secondaryWeapon. This will be used to determine the type of secondary weapon we're using. Again, note that we're putting this into our Game struct, rather than assigning it to the player's fighter directly. This is so that the player can choose which weapon to use between missions.
Finally, we've updated the Stage struct:
We've added in rocketEffectTimer. Like engineEffectTimer, this will be used to control how often our rockets stream flame trails.
With that done, we can move over to bullets.c, where we'll implement our new rocket weapon. First of all, we're updating initBullets:
The only new thing we're doing here is grabbing a texture for our rocket sprite, and assigning it to rocketTexture.
Next up, we've added a new function called fireRocket:
A very simple function. We're basically creating a bullet, and giving it the rocketTexture texture. We're setting its `damage` to 50 and making it live for 2 seconds (via its `health`). We're also testing to see which direction the owner of the rocket is facing (in this case, the player), and setting the rocket's starting `x` position and `dx` (it's speed) accordingly; we want to make sure the rocket goes in the right direction and originates from the front of the firing craft. Finally, we're setting the bullet's `tick` to a new function called rocketTick, and its `draw` function to standardDraw.
So far so good. Now to look at the rocketTick function:
You might remember that the player's bullets are killed off if they leave the screen. Well, we're not doing that test in this function; our rockets can fly until they expire naturally. So, this function merely tests if Stage's rocketEffectTimer is 0 or less, and then creates an engine effect at the rear of the rocket (by calling addRocketEngineEffect, found in effects.c). We're also calling checkCollisions, to see if the rocket has struck an enemy.
That's it for bullets.c! Very simple. Now we can look at the other compilation units that we've updated.
If we look at game.c, we can see we've updated initGame:
We're setting Game's kit's secondaryWeapon to SW_ROCKET, to tell our game we have rockets as our secondary weapon. This is just for testing purposes. In our full game, the player won't have a starting secondary weapon, and will need to buy one.
Now onto player.c, where we've made one update and one addition, starting with doPlayerControls:
We're testing if we've pressed the control for firing our secondary weapon (isControl is found in controls.c). If so, we're going clear the control, and then call a new function named fireSecondary. Unlike when we fire our main guns, we want the player to press the button, rather than hold it down. Our secondary weapons don't have a reload or firing detaly, so this will ensure we don't use up all our ammo in one go, which would be annoying!
The fireSecondary function is defined so:
Another simple function. We're first testing if we have any `ammo` (and also a valid secondary weapon), and then testing which kind of weapon we have. We only have SW_ROCKET right now, so we're calling the fireRocket function. With that done, we're decrementing our `ammo`, since we've just used some.
Finally, let's look at stage.c, where we've updated doStage:
Just like our engineEffectTimer, we're decreasing rocketEffectTimer, and setting it to 0.15 if it falls to 0 or less.
And that's it! We can now fire some powerful rockets as a secondary weapon, so long as we have the ammo to do so. If not, we can just shoot down some enemies, and hope they release the powerups we need (or, later, buy ammo from the Mouse Bros. shop - but that's for another time).
Rockets are a good weapon, and do a lot of damage. What would be better is if we could launch one that will hunt down our enemies, letting us "fire and forget". So, in the next part we'll look into adding in homing missiles!
The source code for all parts of this tutorial (including assets) is available for purchase:
It is also available as part of the SDL2 tutorial bundle: