Monthly Archives: November 2016

Jetboard Joust Devlog #49 – Gun Control

This week I’ve added a couple of extra jetboarding enemies and a new weapon – and I think I have enough content now for a playable demo! Just need to to sort the main menu out (groan) add a few more sound fx and (probably) background music. Here’s a bit more about the new stuff that’s been added…

The Gatling Gun
In operation this is really like a rapid-fire pistol, therefore it was pretty easy to subclass the existing ‘pistol’ weapon and change a few parameters to get it working. The hardest thing was getting the recoil to feel right – I wanted enough recoil for it to feel slightly ‘out of control’ and unwieldy but (obviously) not enough to be unplayable. I’ve given it a slightly lower damage-per-bullet than the pistol but this is more than made up for by the rapid firing.

Improved Shotgun Blast
One thing I realised whilst playtesting was that the existing shotgun blast was just nuking everything within its range rather than taking account of the fact that some enemies would shield others from the blast. Fixing this accurately seemed like it would be a mathematical nightmare (I’m not too strong on geometry) but I managed to implement a slightly ‘fuzzy’ solution which I think will be good enough. What I do is order all the enemies that intersect the blast region by their distance from the gun barrel. I then iterate through them in order creating a vertical ‘blocked zone’ for each one based on the combined height of the previous enemies in the list. If more than 50% of the current enemy intersects this ‘blocked zone’ I assume it has been shielded from the blast.

The Assassin
This type of enemy is pretty similar to the omnipresent ‘minion’ only they don’t try and abduct babies, they just go all out for attacking the player. This enemy uses the ‘skullhead’ sprite that I’d already designed and required no additional AI work (just adjusting existing parameters) so it was really easy to get up and running, unlike the next one…

The Bodyguard
Bodyguards have a pretty specific AI in that their main aim in life is to protect other enemies that are in the process of baby-snatching. I thought this would be pretty simple to get working but it was a lot harder than I thought to get something that looked decent. This is the basic framework of rules I ended up with…

– Bodyguards seek out the closest baby-snatcher to protect
– Once a bodyguard gets close enough to protect someone they’ll never desert them
– Only two bodyguards can protect a baby-snatcher at one time
– If there’s more than one bodyguard protecting a baby-snatcher they’ll stand guard on opposite sides
– Bodyguards never stray to far horizontally from the baby-snatcher they;re protecting but they will move vertically to attack the player

…there’s a bit more to it than that but these are the key AI decisions that are made. Bodyguards have a lot of health but move relatively slowly and I’ve tried to design the sprite to reflect this, hence they look rather ‘chunky’ compared to the other jetboarding enemies.

I haven’t fully playtested all this yet but will be doing so over the next few days as I add the outstanding audio fx.

Dev Time: 3 days
Total Dev Time: approx 83 days

previous | next

Whoops – Too Much Recoil On The Gatling Gun

The Final Gatling Gun In Action

The Magic Shotgun – Enemies Should Shield Each Other!

Fixing The Magic Shotgun

Trying To get The Bodyguard Looking A Bit More ‘Hench’!

Bodyguards Doing What They’re Paid To Do

Assassin Enemies Wielding Gatling Guns – Beware!

Jetboard Joust Devlog #48 –Game (Not) Over

Since the last post I’ve mainly been tweaking – playing the game over and over again, adjusting the various difficulty parameters and noting down and fixing various bugs that crop up. My aim at this stage is to get to the point where I have an ‘alpha’ version that can exist as a playable demo, albeit with a very limited set of weaponry and enemies. I’m getting there!

So, in no particular order, heres some of the stuff I’ve been working on…

The Dawdle Police
I’ve made the ‘bastard‘ enemies operate similar to the ‘baiters’ in Defender in that they only appear once the player has spent a certain amount of time trying to complete a level and (unlike other enemies) don’t need to be destroyed in order to complete a level. More bastards appear the longer the player hangs around adding even more of a sense of urgency to the proceedings.

The Pyramid
Some of the more observant readers may be wondering why there are two warp gates that appear at the end of each level. Well, in a nod to ZX Spectrum ‘classic’ The Pyramid, the gate you choose affects the level you’ll appear in next, so rather than a linear arrangement of levels we have a pyramid-type structure with each row defining the difficulty level and each column a different combination of enemies, terrain and weaponry. I will probably add special collectables at certain locations to add an exploratory element to the game. I’ve always had this functionality planned from the start but have only just implemented it properly.

Mutant Frenzy
In another nod to Defender, now if you’re careless enough to let all your babies get abducted a ‘mutant frenzy’ is unleashed! Every jetboard-riding enemy mutates and every remaining attack wave is released. Basically it’s total chaos and you probably won’t last long after this happens!

Score Combos
Killing enemies in quick succession now ups a bonus multiplier which multiplies both the score and cash awarded. It’s a good way to earn extra cash and I like the way it adds to the ‘pinball’ feel of racking up large amounts of points.

Extra Lives
Extra life pickups now appear when a certain score threshold is reached. You’re going to need them!

Game Over
I’ve added a fixed number of lives per game and the ‘game over’ message. Spent quite a while tweaking the ‘game over’ effect!

Jetsuit and Jetboard Upgrades
I’ve now fully implemented the code that makes your jetboard and jetsuit upgradeable items. The upgrade state of all equipment is now persistent across games.

Plus a myriad of other small improvements and bugfixes.

I may now add one extra weapon type (machine gun) and possibly a couple of extra enemy types before moving on to add a few elements of missing game audio, background music, and then a first implementation of overall menu UI.

Dev Time: 5.5 days
Total Dev Time: approx 80 days

previous | next

Kill Enemies In Quick Succession For A Bonus Multiplier

You’re Gonna Need An Extra Life Or Two…

Must… Try… Harder… Next… Time…

Your Jetsuit And Jetboard Are Now Fully Upgradeable

Jetboard Joust Devlog #47 –Having Difficulty With Difficulty

With all the core gameplay elements pretty much in place it’s time to get back to some serious gameplay testing and start thinking in more detail about how I manage the difficulty curve within the game.

I’d already put quite a bit of thought into this as discussed here, but, as is so often the case, Jetboard Joust has grown in complexity fairly significantly since I posted that and my ‘procedural difficulty’ code needed to be reworked in a major way.

I’m still starting from a similar standpoint in that I allocate a difficulty value for each level and then create random waves of enemies that total that difficulty score. Now, however, I have different RPG-style ‘character-levels’ of enemies and weaponry to consider.

Firstly what I do is allocate a series of character-level ‘stats’ to each enemy and weapon type. I set a minimum and maximum value for each stat and the values in between are calculated automatically. Some values (e.g. health, weapon range) are consistent across all enemies and weapons but not all. Every weapon and enemy has a ‘difficulty’ stat.

I then create an EnemyDefinition for each enemy/weapon combo. This is a lot of definitions as I have to have create a separate definition for every combination of each character-level of enemy and weapon.

When a level is created my first approach was to split the total difficulty score into a set of six ‘batches’ of enemies that are released at set time intervals. The enemies that make up each batch were chosen at random from the EnemyDefinition collection. If a batch of enemies is destroyed the next one is released immediately.

This worked pretty well but the combination of enemies was too random and in order to get a more playable selection I needed to implement a few restrictions…

1. Every enemy and weapon type have an ‘intro level’ so that they don’t appear until a certain level of the game has been reached.

2. Every enemy and weapon type have a’level up rate’ that affects the way their ‘character-level’ progresses throughout the game – so, for instance, an enemy with a ‘level-up rate’ of 2 and an ‘intro level’ of zero could only appear at character-level 1 for the first two levels of the game, then at character-level 1 or 2 for game levels 3 and 4 and so on.

3. Only certain enemies will try and abduct the alien babies(!) – as this is fundamental to the way the game plays I needed to ensure a certain amount of ‘baby-chasing’ enemies per batch. I know that sounds a bit dodgy!

After implementing these restrictions the enemy selection was much better but I realised the process was still flawed. As I was choosing enemies from the set of EnemyDefinitions at random (albeit with the above restrictions) the selection was skewed towards certain types of enemies. There would always be many more valid definitions for lower ‘intro-level’ enemies (especially as we have a definition for every character-level and weapon combo) resulting in far too many of certain enemy types in the game.

To solve this I needed to create a structure to store the valid EnemyDefinitions that was not simply a flat list – so I created the wonderfully-named EnemyDefinitionBucket class.

A EnemyDefinitionBucket contains a horrible-looking data structure that’s defined like this…

SortedDictionary<EnemyTypes, SortedDictionary<WeaponTypes, List>> dictionary; first we have a collection of every valid EnemyType in the bucket, then for each EnemyType a collection of each valid WeaponType, and finally for each EnemyType/WeaponType combination a list of each valid character-level of enemy and weapon that fits that combination.

Now when I choose a random EnemyDefinition I first select a random EnemyType, then a random WeaponType, and finally a valid EnemyDefinition that matches that combination. This ensures that all enemies and weapons appear on equal footing.

Only that wasn’t quite good enough! In practice the enemy/weapon selection needs to be skewed towards those that have an ‘intro level’ nearest the current game level. Hence the reason I have used SortedDictionary rather than a standard Dictionary – this way the enemy and weapon type ‘keys’ can be indexed in order of ‘intro level’ and I can implement a sine-based distribution curve that favours the ‘higher’ items when choosing at random. The EnemyDefinitions are also stored in a sorted List and selected in a similar way.

Finally I think that’s done it, now on to tweaking the various ‘character stats’ which is another rabbit-hole.

And, sorry, this post doesn’t contain much to look at so I’ve just included some random gameplay footage – finally found an app Capto that grabs at 60fps!

Dev Time: 3 days
Total Dev Time: approx 74.5 days


The Current State Of Play