PC Games
• Orb Tutorials
• 2D shoot 'em up Latest Updates
SDL2 Versus game tutorial
Download keys for SDL2 tutorials on itch.io
The Legend of Edgar 1.37
SDL2 Santa game tutorial 🎅
SDL2 Shooter 3 tutorial
Tags • android (3) • battle-for-the-solar-system (10) • blob-wars (10) • brexit (1) • code (6) • edgar (9) • games (43) • lasagne-monsters (1) • making-of (5) • match3 (1) • numberblocksonline (1) • orb (2) • site (1) • tanx (4) • three-guys (3) • three-guys-apocalypse (3) • tutorials (17) • water-closet (4) Books H1NZ Arriving on the back of a meteorite, an alien pathogen has spread rapidly around the world, infecting all living humans and animals, and killing off all insect life. Only a handful are immune, and these survivors cling desperately to life, searching for food, fresh water, and a means of escape, find rescue, and discover a way to rebuild. |
— Making a 2D split screen game — Note: this tutorial assumes knowledge of C, as well as prior tutorials.
Introduction Up until now, we've not had a proper game loop. Either it is impossible to win a match or the game stops once someone wins. That's no good, at all. What we want is for the game to continue on once someone wins, changing zones if requested. This part finally establishes our main game loop, so that the game can continue on after a player wins one of the matches. Each time the match is finished, we'll move to next zone, randomly. Ultimately, this behaviour can be configured by the players themselves. Here, however, we've hardcoded the conditions (1 life each, random zone switching). Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./versus15 to run the code. You will see a window open like the one above, with each player on either side of our zone. Use the default controls (or, at your option, copy the config.json file from a previous tutorial, to use that - remember to exit the game before copying the replacement file). Play the game as normal. To speed things up, each player only has one life. Each time a player wins a match, the game will randomly move onto a new one. Once you're finished, close the window to exit. Inspecting the code Our code changes are simple, and mostly involve cleaning things up once the match is over, to prevent memory leaks. Let's start with defs.h:
We've added a new define called NUM_ZONES. This is the set number of Zones in our game, which will be used when we randomly choose a Zone to move to. Now for zone.c, where the first of our major changes lie. First up, we've updated initZone:
The function now accepts an int parameter, called `n`. This is the Zone number. We set a new static variable called zoneNum to the value of `n`, and then use that in the calls to loadWorld, and the new function loadEntities. (for the purpose of this part, we're setting our goals to 1 life per player, and unlimited targets for everything else - included in this code above, for the sake of context and completeness). Over next to `logic`:
One simple change here. We're now checking if gameOverTimer has fallen to -5 seconds, and calling a function named nextZone if so. This gives us a small delay after the WINNER / LOSER! text is displayed on screen before we move to the next match. The call to nextZone will set this up. nextZone is an easy function to understand:
We start by calling clearZone, a function that will tear down all our data (deleting entities, bullets, particles, etc), and getting everything back into a ready state. Next, we test if Game's zoneNum is not -1. If so, we'll use that number as the zone to load. This is will be the case if the players have opted to play the same zone in the options. Otherwise, we'll randomly pick a zone to play. Note that our Zones start from 1. -1 will mean random (there's a reason why we're not using 0 here, and it's to do with our widgets and configuration..!). Now for clearZone:
This function is simply responsible for deleting all the entities, bullets, etc. that currently exist. It delegates to the appropriate "clear" functions. We'll cover these briefly later. That's all the changes needed to zone.c. Let's now take a look at the new loadEntities function we've created in entities.c:
This function takes the zone number (zoneNum) as a parameter. It then attempts to load a corresponding JSON file. So, zoneNum of 2 will load "data/zones/02.json", for example. The JSON file simply contains an array of JSON objects that detail our entities. There are just three attributes per object: `type`, `x`, and `y`. `type` is the type of entity, while `x` and `y` is the location of the entity in the zone. We loop through all these entries, extract this data, and then test the `type`. We'll create the appropriate player for "player1" and "player2". Our aliens will be created for types of "orangeAlien", "purpleAlien", or "redAlien". Note that we first test if our game permits aliens to be added before testing these values. If aliens are not allowed, no aliens will be created. So, we're just loading a JSON file, and creating our entities based on the available data. In previous tutorials, we've used an entity factory for this. We're skipping that here, as our game is much similar than those others. What follows now is general clearing up function that we'll use when resetting a zone. We'll have seen these all before, so we'll gloss over them quickly. Starting first with clearEntities:
We want to ensure we delete all our entities here, both those alive and those waiting to respawn. bullets.c has its own clearing function:
As does particles.c:
As for the environment itself, we want to delete all the Triangles we created in world.c, when loading that data:
For out spatial grid, things are equally as simple:
We need only loop through each of the cells in our grid, and free the pointers arrays if they are non-null. That's everything cleared. When initZone is called to create a new zone, the init functions for everything will be called again (initEntities, initBullets, etc), to set things up for our game; we're effectively creating a clean slate to work with. The last little thing we need to do is update main.c, to make initZone start with a random:
Our game loop is done! We can play as many matches as we like, and the winner count will be retained and incremented as we go. But our game conditions are still hardcoded! We need to fix that, so that the player can choose how they want to play. So, in Part 16, we'll look at allowing the players to configure the matches the way they like. This can easily be done, using our widgets. Purchase The source code for all parts of this tutorial (including assets) is available for purchase, as part of the SDL2 tutorials bundle: From itch.io |