• 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 —
We have all our icons and widgets setup for our shop, so it's now time to introduce all the buying and equipping logic. As you'll soon, there is a little more to it than simply pressing the "Buy" button.
Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./shooter3-18 to run the code. You will see a window open like the one above. Use the mouse to control the cursor. Click on the various shop items (in grey) to view information about them. Click the Buy button to purchase items. For various reasons, the Buy button might be disabled. Purchased secondary weapons can be equipped by clicking the Equip button. Only one secondary weapon can be equipped at a time. Once you're finished, close the window to exit.
Inspecting the code
Let's jump right in. We've had to make a number of changes outside of shop.c to make our purchasing work. We'll start with defs.h:
We've added in a bunch of defines to specify limits to our upgrades, including output, reload (fire rate), health, damage, and ammo.
Next, we've updated structs.h:
We've added in a new field to Game's kite - ownedSecondaryWeapons is an array that will flag which secondary weapons we own. This will allow us to offer them for purchase and equipping in our shop.
Now to shop.c itself. We've both added new function and modified existing one. Starting with initShop:
We're calling a new function here named adjustShopPrices. We'll see this at the end, but it basically does as its name suggests - adjusts the prices on offer in our shop, based on what we already own. Next, we're setting the actions for our buyWidget and equipWidget, to make them call doBuy and doEquip, respectively. We've also enabled them by default.
doItems is the next function to be updated:
We've actually added a single line here to set a variable called secondaryWeaponId to the value of the selectionItem's `id`, less the value of SI_ROCKET_LAUNCHER. What we're doing here is aligning the value of SI_ to SW_ (so, SI_ROCKET_LAUNCHER will align to SW_ROCKET, etc). We're getting away with it here, since our weapon order lines up when the maths is done. If we wanted a safer approach, we could use a switch statement or if-test to get the value we want.
Now for doShopButtons, and as you can see, the function has grown quite a lot:
What this function is doing is performing all the logic to see if the currently selected item can be purchased or equipped. We set three variables here: canBuy, canEquip, and maxedOut (the latter being static in shop.c). We first check if the player has the catnip required to buy the item, then perform individual checks on the item itself, to see if we meet the requirements. For example, we can only repair the KIT-E if our health is less than the maximum, and can only upgrade our damage if it's less than MAX_KITE_DAMAGE, etc. Our default clause will assume we're working with a secondary weapon, and check if we don't already own the weapon. The maxedOut variable is used for aesthetic purposes, and is set to the inverse of canBuy for max health, ammo, rate, damage, and output.
The canEquip variable is set based on whether we've currently selected a secondary weapon, that we own that weapon, and that we don't already have it equipped.
Lastly, the Buy and Equip widgets will be enabled or disabled based on the values of canBuy and canEquip.
So far, so good. Now let's look at the doBuy function:
This function is tied to the Buy widget, so can only be invoked if that widget is enabled. This function is responsible for actually purchasing the item we have selected. We perform a switch against selectedItem's `id` to see what we're buying, and apply the appropriate logic. Most cases do as you would expect (increasing ammo, health, etc). When it comes to health, if we are already at maximum health, we'll increase that alongside it, so that we don't need to also repair the ship when we increase our health..! For our secondary weapons, we're simply setting Game's kite's ownedSecondaryWeapons flag to 1, using the value of secondaryWeaponId.
With the item purchased, we're deducting the price from our catnip, and then calling adjustShopPrices (we'll come to this function at the very end).
The doEquip function comes next, and is very simple:
Just one line. We're setting Game's kite's secondaryWeapon to the value of secondaryWeaponId.
We're almost finished. Just two function left to consider, and our shop is complete. Next up is drawItemDescription:
We've updated the text that is displayed for `footer`, since we won't be displaying the price at all times. If the maxedOut variable is set, we'll be printing "MAXED OUT!". If we're not using a seconday weapon or do not own the secondary weapon currently selected, we'll display the price. Finally, if none of the above apply (meaning we've selected a seconday weapon that we can't buy), we'll be printing "SOLD OUT!" Apparently, the Mouse Bros only keep one of each secondary weapon in stock..!
The last function to look at is adjustShopPrices:
What we're doing here is setting the prices for various items and services in the shop, based on the current stats of the KIT-E. In short, the next upgrade or full repair will become more expensive with each upgrade. We're calling this function in both initShop and doBuy, to set the prices initally, and make adjustments upon each purchase.
There we go! Our shop is now complete. I'm sure you'll agree that splitting this in two was the best approach, as it would've all been too much to take in in one go. The next section that we're going to look at is our stats screen. This is going to be a very easy section compared to those that have preceeded it, giving us a bit of a breather.
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: