• 2D shoot 'em up
SDL2 Rogue tutorial
SDL2 Gunner tutorial
SDL2 Shooter 2 tutorial
SDL2 Widget tutorial
SDL2 Adventure tutorial
The Making Of
The Pandoran War is a 2D mission-based space shooter, based on my Battle for the Solar System space opera novels. The following is a short article about the development of the game, including what went right and what went wrong. It should be of interest to both developers and non-developers alike.
What came before
While I had always intended to make a game based on my space opera novel trilogy (I actually created one way back in 2009, and another in 2014 - more on these in a bit), this game didn't actually begin life as such. For years, I had attempted to create a multiplayer game; I wanted to make a simple network-enabled game, where players could connect to a host and play together. It sounds easy on paper, but network programming is not all that easy, and there is a considerable amount that needs doing to ensure a seamless experience. The premise was basic: an arena shooter, using spaceships. Fly around, blast your opponents to bits, collects powerups, etc. The one that scored the most points would win. Simple.
I never got much further than attempting to write the network code. As in the past, I found that keeping the client and host in sync was a tricky process. Snapshots of the game state are meant to be sent from the host to each of the players (as I understand it), with the player effectively sending requests to the server to take their actions. After working at this for a few weeks, I could see I wasn't going to have any luck this time around, either. I quickly decided to bin off the idea and do something else. It was then that I decided to pick up the TBFTSS game from 2009 that I had cancelled. I had already started using the sprites from the cancelled game as placeholders in my networked arena shooter, and so I felt that maybe this time I could make something of it.
After the failed arcade shooter BFTSS game, I tried making a strategy game on Android. This, again, only went so far before I decided it wasn't going to work; this was mainly due to me not being too fond of making games for mobile phones; I made a Blob Wars, and a puzzle game called Three Guys, but that is about as far as it went. I prefer the freedom that comes with desktop development, as I find it just that bit more flexible.
It was an interesting game to make, but not quite what I wanted at the end of the day. I decided that I wanted something that was truer to the events of the books, and wouldn't leave anyone who played the game first feeling jarred at how things actually turn out. I binned off the project when it was around 90% complete, but at least I had things such as a number of sprites, and star system names that could be used in the arcade-style game that was to come.
I decided to stick with the original idea of creating a 2D mission and objective-based game, rather than attempting to create a fully fledged 3D shooter. Sticking to 2D would speed up development time considerably, and allow the game to be more portable (I had already decided that the source code would be GPL-licensed). To prevent the game from becoming too samey, I thought it would be good to give the player some freedom when it came to choosing which mission to tackle. I didn't want the game to be too linear, and so implemented a system similar to Metal Blob Solid, where one mission could become available to play so long as a certain number of other missions had been completed beforehand. There was also the added restriction (for the purposes of storytelling) that some missions would only present themselves once a certain other had been finished.
The begin with, each mission had a certain number of challenges that the player could aim to complete in addition to the main objectives. For example, in the first Temper mission, the player would need to finished the mission in a set amount of time, with a certain accuracy, and having taken down a certain number of the enemies themselves. Around v0.3 of the game, I dropped this in favour of a separate Challenges mode that could be played, instead. I did this knowing that some players might prefer only to play the challenges and have no interest in the campaign, as well as wanting to close off a mission once it had been finished (although all the missions are playable in free play mode after finishing the campaign itself).
The HUD during missions also went through a number of iterations before the final UI was decided upon. At the start, the player's missiles were depicted as a series of orange boxes on the top-left, beneath their armour and shield. The current target's health was also displayed on the right-hand side. Sometime later on, I dropped the target's health entirely, and presented just their name and distance from the player. The health bars returned later when I noticed that many modern games (RPGs and the like) display enemy and NPCs' health bars above them during combat.
One thing that struck me about the game early on was just how difficult it was. This wasn't because of unfair mechanics, but because of the nature of the game itself. Once an enemy had you in their sights, they would be hard to shake off, and would pursue the player until they had been wiped out. I countered this in two ways. First of all, I gave the AI a chance to abandon and break off from their current target every once in a while, as well as take evasive manoeuvres if they were being shot up a bit too much. This meant that turning around and opening fire on a enemy giving chase could cause them to flee, granting the player a small reprieve. The other additions I made was an arcade-style speed boost, and ECM. When invoked, the speed boost would allow the player to accelerate away at a rapid pace for about a second. It doesn't sound like a lot, but it came a very useful, and often life saving addition. The other player-only advantage was the ability to activate an ECM, and destroy incoming missiles. Before the addition of the ECM, a missile fired at the player would have a 99% chance of hitting them, as they were near-impossible to dodge (fun fact: there is a trophy in the game for evading 5 missiles!). These two add-ons made the game easier to play, and made it a lot more fun to play. While both are unlimited, they do take a few seconds to recharge, so knowing when and where to use them is still important.
I decided very early on in the game's development that I didn't want to player to go into the battles alone, and would pretty much always be accompanied by AI team mates. The trickiest part of creating the wingmates was making them seek out the player and move into position alongside them; I didn't want them to be jostling for space, flying in circles, or even flying over the top of one another. After some research, I found the best solution was to write a flocking routine. It meant that the fighters could move to and follow the after the player (or other craft that was designated as their leader), while keeping pace, and maintaining a sensible separation distance. It took a little while to get right, but the results were well worth it. Besides the ability to follow a leader in formation, there were other benefits to the routine, such as tagging a unit that needed to be defended as a leader, and knowing the fighters would follow it around.
Things were going well, but after a time I noticed that the game would become quite quickly dull if the only enemies that were ever encountered were starfighters; the game's arena battle roots were starting to show, and so I set about adding in tugs, shuttles, civilians, and static cannons. The tugs were used in missions were the player needed to bring a stranded or disabled ship back to a jumpgate. To make things more interesting, I decided that the player would sometimes need to defend an AI-controlled tug. This seemed daunting at first, knowing that I needed to create an AI system that could not only seek out a disabled ship to latch onto, but also bring it home, and avoid enemy fighters. Thankfully, my work on the flocking routine once again helped with telling the tug to avoid dangerous situations. The shuttles followed a similar design process, and were used to pick up cargo, and other items. The shuttle is only of the only craft in the game that doesn't have any weapons, and so needs a lot of protection.
Friendly fire was one gameplay mechanic that I also considered for a time, but, as if the way, I found that the AI ended up killing each other far more often that I would have liked. There is, of course, line of sight checking in the game, but stray fire in a 2D game causes far more casualities than is acceptable. Had the game been 3D, it would most likely have been kept in. I didn't remove it entirely, however. In order to prevent the player from becoming reckless during certain missions, I allowed fire from any side to cause damage to the ship that had been disabled. This meant the player would need to lure opponents away from craft that needed to be kept alive, and thus added an element of challenge.
For the adventurous, friendly fire can actually still be activated in the game by editing the config file, and setting 'friendlyFire' to 1. Missiles can also be told to select a new target if their original is destroy by changing 'missileReTarget' to 1.
The final little gameplay mechanic that I added was for some enemies to either flee or surrender during battles. In most cases, a fleeing enemy would need to be either killed or disabled before they reached the jumpgate and escaped the system. The mission would end in failure the moment they did so. Likewise, if an enemy were to surrender, they would disengage from combat, and run away. It would then be up to the player (or another fighter!) to disable their fighters. This was used a plot point in the campaign.
Once all the fighters had been completed, I set to work on creating some capital ships. I knew I needed something other than the fighters, tugs, and shuttles in order to keep things interesting. I'm not an artist, far from it, and so the thought of creating something as big as a corvette was somewhat daunting. I could have ploughed the offering of free game art to find something suitable, but I wanted to keep the ships unique to the game. It would look a little cheap and lazy if the capital ships could clearly have been seen having been plucked from other open source games. The styles, too, wouldn't match. After a lot of failed attempts (at one point even trying using Inkscape), I followed some step-by-step tutorials of how others had approached the drawing of the ships. My first successful capital ship came out somewhat blue and flat, but I was happy with it. A few days later, I made some tweaks by playing with layers and blending styles in GIMP, and ended up with a ship that had more depth to it. With that done, I outfitted the things with guns, engines, and components to shoot to destroy it; I figured it would be more interesting for the player to need to target specific parts of the ship to destroy it, rather than simply aiming for the body as a whole. Breaking them down into separate parts also enabled me to allow the player to knock out the engines and guns separately, something that became key in missions where the player had to disable a capital ship. In the end, I was pleased with the results. The capital ships are genuinely dangerous to approach, and (unless the player is piloting an ATAF) would require the work of a number of fighters in order to take down.
A scripting system made its way into the game around halfway through development. It was a hand-rolled thing, not using anything like Lua or Squirrel, as I only needed something simple. The introduction of the system opened up the game massively, and allowed for the trigging of events based on things like times, locations reached, enemies destroyed, etc. It also allowed me to create message boxes, and add chatter. It wasn't an amazing system, and some things still needed to be handled in the main C code, but it was sufficient for my needs.
Maintaining the canon
The ATAFs (Advanced Tactical Assault Fighters) are the most powerful starfighters in the books, and, as they are flown by the White Knights, the principle characters in the trilogy, it would've been wrong for them not to make an appearance. Inserting the ATAFs into the game was certainly an interesting experience. As they are virtually indestructible (almost - there's a trophy for being destroyed while piloting one!), any missions where the player got to pilot one was a cake walk. The first time the player encounters the ATAFs is the first Coyote assault mission. However, I decided that to begin with, the player would pilot a different fighter and watch the AI control the ATAFs. It was teasing, for sure, but I felt it was important. First off, I didn't want the player to gain control over the ATAFs so early in the campaign, as it should be something to look forward to. Second, it could lead to a yo-yo in difficulty. I didn't want to player to experience a mission early on where they could be reckless and not worry about their shields, and then be thrown into a TAF or Nymph where a single missile could take them out.
Many years back, when I was first developing the book trilogy, I added pages to the dedicated website detailing the various starfighters' armaments. For the most part, I stuck to these when I implemented the craft into the games. I was forced to make some minor changes here and there, but nothing drastic. I did, however, purposely leave out the ATAFs' plasma accelerators. In the books, the accelerators are a devastating weapon that are usually found only on capital ships and orbital defence platforms. The ATAFs, as is their nature, are the only starfighters in existence to come equipped with them. Adding the weapon to the game would massively overbalance things, with a single sweep of the beam being enough to eliminate all enemy fighters in its path, and cause major damage to a capital ship. Even if I had added in a 5 minute recharge time to the PAs, they would remain overpowered, and so were never implemented.
The Darts were a fun enemy to create, as the ship is known in the BFTSS universe as being of a non-fixed configuration. This meant that when the game created a 'Dart' fighter, it would randomly assign weapons, armour, shields, speed, and colour to the ship. They remained relatively easy to take down, however, and were never as powerful as a dedicated fighter.
While adding the fighters to the game, I became aware that not all weaponry was being catered for equally by all sides. The CSN, for example, were lacking a starfighter equipped with laser cannons, a weapon that could be used against a target's shields to rapidly diminish them, and cause a greatly increased recharge time, making the target easier to take down. I therefore created the Kingfisher, a fighter that does not appear in the novel trilogy (or is even mentioned). The UNF also received a bomber known as the Lynx, to fulfil that missing unit from their compliment.
Naturally, characters from the trilogy were incorporated into the game. One of the first pilots you play as is Katherine Strictland, a wing commander based in the Temper system. Katherine is mentioned in the books, but doesn't actually make an appearance. Members of her squadron, The Steel Bulls, do, however, and the player often finds themselves undertaking missions either alongside them, or controlling them directly. As for the White Knights, the player will also find themselves either fighting alongside Dodds, Estelle, Chaz, Kelly, or Enrique, as well as controlling them directly. It was a lot of fun to incorporate the characters into the game, as well as pluck out some of the more obscure ones and give them a little more exposure.
Expanding the universe
During the last major battle in the novel trilogy, Dodds encounters a bunch of bombers that the Pandorans acquired from an unstable nation during their campaign. I had always decided that the Pandorans would not be the only enemy that the allied forces of the CSN and UNF would face during the upheaval of the galaxy, and so I started to look into ways to expand the storyline. I chose to incorporate an event in which a system known as Tzac would leap on the chance to attack neighbouring star system while they were busy dealing with the Pandorans. The Kingdom of Tzac was ruled by a woman called Empress Christabel IV, who believed that the galaxy rightly belonged to her, and so chose to seize it during the war.
For the purposes of this, I first designed a number of new starfighters: the Blizzard, the Razor, the SK-31, the SK-34, the Shale (based off the stolen schematics for the UNF Nymph), and, of course, the Khepri bomber. I elected to use a green colour scheme for these fighters, in contrast against the reds of the INF, the whites of the UNF, and the blues of the CSN. Corvettes followed, and once that was all set and done, and moved onto making missions, and weaving a plot into the universe.
The basics of the mission thread was that the Tzac forces would battle against all other sides, sometimes jumping into system in the middle of another mission to disrupt the proceedings. I also introduced missions where the Pandorans had acquired some of the Tzac fighters (as is their way) and turned them against the allied forces. During the mission development, I decided that it might be interesting to add in some missions where anti-war protests had become more prominent throughout the galaxy, and so chose to have missions specify that the player must not kill any enemies, but instead disable their fighters (or only destroy a set amount of them). It made for an interesting break from the standard missions, and made the player have to act more carefully.
The battle against Taz does not last long in game terms, and ends with the allied forces closing in on Tzac, and assaulting the planet to arrest the empress. The plot thread ends with the disabling of Christabel's shuttle, which she then goes on to self-destruct, rather than accept capture. I enjoyed working on that part of the game, as well as the whole threat from the Kingdom of Tzac aspect, and so have declared it to be part of the Battle for the Solar System's canon.
While there are no real missions set in Mitikas space, I thought it might be interesting to add in some optional missions for the player to try out. These optional missions involved the acquisition of a rare INF fighter, known as an Angel, and the subsequent infiltration of the Pandoran forces to search for Jason Zackaria. I had the original mission to steal the fighter be undertaken by a pilot called PJ Burgess, who appeared in THE HONOUR OF THE KNIGHTS.
With the Angel secured, the player was tasked with blending in with the Pandoran forces, and attempting to work their way to a meeting with Admiral Jason Zackaria. However, I decided that in order to blend in, the player would need to fight alongside the enemy, which involving slaughtering civilians, as well as taking down members of the allied forces. Failure to comply with such things, as well as straying too far from the Pandoran wing commander, would result in a suspicion meter gradually rising. If the meter got too high, the Angel would be called out, and the Pandoran forces would turn on the player. I also changed the text of the message boxes when the Pandorans are speaking. In the books, the Pandorans are said to be code talker, their language almost impossible to understand. I therefore used a font that couldn't be understood by the player, meaning they would need to work out what was going on my mimicking the actions of their wingmates.
As one final nod to the events of the books, when the player did finally encounter Zackaria, they found the admiral piloting a custom Sphinx, that, in contrast to the other INF fighters, was sporting a blue and white colour scheme. Zackaria pilots the very same fighter during the final major battle in THE ATTRIBUTE OF THE STRONG (the eponymous battle for the Solar System). I was excited for putting the encounter in; I felt it was a nice little touch for those that had read the books. Kyle Hicks then becomes the only other member of the CSN to whom Zackaria actually speaks, even if it is rather brief.
What went missing
While The Pandoran War was a result of a failed attempt to create a multiplayer game, I still would have liked to have added a multiplayer mode to it. There could have been missions created just for multiplayer, ones where the players would need to work together to complete the objectives. Of course, the usual deathmatch games would be in there, too. Alas, this was not to be, and so I stuck to leave the game as a purely single player experience.
A more technical aspect of what went missing was allowing the player to keep moving beyond the confines of the battlefield. When approaching the edges of the battlefield, the player is warned that they need to turn around. If they don't, they will eventually hit the edge of the game world, and be pushed back. Ideally, I would have liked the game to wrap around, with the player emerging from the bottom of the map. Ordinarily, such a thing can be accomplished by teleporting the player to the other end of the map, and using some clever functions to ensure any entities that should be visible could also be seen. The major problem I encountered was the quadtree, that was used for both collision detection and rendering. Moving the player to one end was somewhat tricky, as they need to exist in all the relevant areas at the same time. And so did everything else! The AI would also need to be aware of the open-ended nature of the map, and it would need to be able to collect data about everything at the edges. It could be very prone to errors, and would likely result in some strange effects.
There was an advantage to keeping the player and everything else confined to a battle space: I was able to add allies and enemies outside of the battlefield, and have them enter was needed. This stopped the enemies from simply popping into existence while you were next to them. This was especially helpful when dealing with large entities, such as the frigates.
I imagine that there are quite a number of players who - quite understandably - are wondering why the game ends where it does, and doesn't proceed further into the Helios-controlled star systems. The reasons for this are two fold. The first is that I really wanted to focus on the period before the commencement of Black Widow (a major operation from the novel trilogy that has game changing implications for the allies). The second is that I essentially ran out of ideas. I saw after a time that the missions were starting to repeat themselves. The game contains 82 (including training and optional). That's quite a number for an arcade shooter. I didn't want to to create a game with 150+ missions, that began to repeat halfway through. So, I decided after Alba had been overrun by the Pandoran forces that I would end things there.
There are a few things that remain outstanding, the most notable of which is i18n. While the game does support multiple languages via gettext, there sheer amount of text that requires translating must be quite daunting for translators. I'm also not entirely convinced that using gettext is right for parts of the game; its really more appropriate for single words or short sentences. BFTSS, being a game, contains some paragraphs of text that need translating. It might be that using placeholder labels would be better for performance reasons. The other outstanding issue also relates to text. SDL 2.0 does not support sprite batching, and so to render text I had to create and cache the string texture, but looking it back up on subsequent redraws. To make use of batching, I would need to rewrite a lot of the drawing routines, something that would take some time. For now, the current solution works, though its far from ideal. Still, the rewrite might happen one day.
Whether I will make any more games based on the novel trilogy is hard to say. I did at one time have an idea for another turn-based strategy game, this one based on the invasion of Mythos. You would command John Stafford's team, as they fought back against the Pandoran forces that had attacked the planet, and looked to survive the conflict. I could see the game being somewhat canon, though I would also get creative with some of the events that took place. Maybe one day.
Total development time : ~12 months Lines of code : ~20,000 Size of source : 586K Size of data : 750K Size of graphics : 3.5M Size of sound : 805K Size of music : 56M Number of missions : 81 (inc. optional) Number of challenges : 93 Number of spacecraft : 50 Number of trophies : 44 Estimated gameplay time : 11 - 12 hours