Monthly Archives: May 2016

Jetboard Joust Devlog #32 – Knob Rocket

Rather a frivolous blog post this one but I feel I should document everything, warts and all – and this issue has cost me a worrying amount of time.

I needed to add a rocket pickup so I could limit the use of the jetboard ‘jump’ attack (will write more on this in the next post). This should have been a simple task but unfortunately my ‘pixel rocket’ ended up looking rather too much like a ‘pocket rocket’!

I tried an alternative which I thought was OK but several people on Twitter though it was still too phallic so it was back to the drawing-board again.

Eventually I got there. The issue really was that the ‘shaft’ of my rocket was only two pixels wide – this meant that the end always looked ’rounded’ instead of ‘pointy’. Thickening the shaft to three pixels allowed me to have a pointy end which, I think, removed any sexual connotations for all but the most filthy-minded of individuals (I can’t believe I’m actually writing this).

Oh yeah – I’ve also added a new enemy type, I’m calling this one the Minion!

Dev Time: 0.5 days
Total Dev Time: approx 33.5 days

previous

mockup_3x
Pixel Rocket Or Pocket Rocket?

mockup_3x
The De-Willification Procedure

mockup_3x
Final Rocket Pickup In-Game

mockup_3x
Introducing The Minion

Jetboard Joust Devlog #31 – Attack Procedurals

In order to test the gameplay for Jetboard Joust I needed to start to thinking properly about how enemies are going to appear. Originally I was imagining that all enemies would spawn at the start of each level, however a few initial tests have led me to realise that that approach won’t work for two reasons 1) The player is too likely to become overwhelmed at the start of the level and 2) The difficulty of the level would tail off too much as enemies are destroyed.

So – in order for levels not to feel too ‘front-loaded’ I’m going to have enemies spawn in batches after a certain amount of time has elapsed, much like in Defender.

I also needed to think about the logic behind the choice of enemies in each level. As there will be an infinite number of levels in the game they will have to be procedurally generated somehow – my ideal scenario is to allocate a difficulty score for a level and have an algorithm allocate a spread of enemies that matches it without feeling too ‘random’.

The problem is complicated by the fact that many enemies are a combination of two factors, enemy type and weapon type – so allocating a simple difficulty score per enemy type won’t wash.

The solution I’ve come up with so far (which may well change) is as follows…

I have three separate enums WeaponTypes, EnemyRiderTypes and EnemyTypes. The two different enemy types represent ‘armed’ jetboard riding enemies and ‘standard’ enemies. The values allocated to each element in the enum represent a difficulty score, e.g…

I then have a new class EnemyDefinition which represents an enemy to which a difficulty score can be allocated. This could be either a standard EnemyType or a combination of an EnemyRiderType and WeaponType. EnemyDefinition also has a method EnemyDefinition.Create() that creates an instance of the enemy it defines.

At startup I automatically create a list of EnemyDefinitions which contains an entry for each EnemyType and for each possible EnemyRiderType/WeaponType combination – I store this in a static class EnemyRandomizer.

Now I have a static method EnemyRandomizer.CreateBatch() which takes a parameter for a total difficulty score and a parameter for the current level. This method creates a list of all EnemyDefinitions that are equal or less than the supplied difficulty score and chooses one of these at random. It then calls EnemyDefinition.Create() as many times as necessary to create enemies that total the supplied difficulty score and returns this ‘batch’ in a list.

When I originate a level I take a difficulty score based on the level number, split this into a series of ‘batch’ scores and then call EnemyRandomizer.CreateBatch() for each one – so a level with a difficulty score of 500 might have five separate batches with a difficulty score of 100 each. These ‘batches’ spawn at a preset time interval or when all existing enemies have been destroyed.

There’s a few extra complications such as making sure we don’t get ‘stray’ enemies and stuff but this is the basic approach and (for now) it seems to work OK. Hopefully it’ll prove robust enough to be used for the final game.

Dev Time: 0.5 days
Total Dev Time: approx 33 days

previous | next

mockup_3x
Oops – Rather Too Many Enemies!


Jetboard Joust Devlog #30 – Crossed Platforms

Porting From Mobile To PC with MonoGame
This week I was supposed to have started on the initial gameplay testing for Jetboard Joust but I came up against a rather nasty snag.I develop using Xamarin Studio on a Mac and had been using the GenyMotion Android emulator for my main testing platform. This probably seems strange given that my main target platform is PC, but GenyMotion generally runs extremely well and I don’t want to have to buy another machine just for development purposes. Unfortunately I discovered a problem with GenyMotion in that it seems to just ‘miss’ some keyup/keydown events. The problem is intermittent but bad enough to make serious gameplay testing on the platform impossible – no response from their support either.

That means I need another platform for testing. The iOS simulators are hopeless for graphics performance (and don’t respond to keyboard control as far as I’m aware), Google’s stock Android emulators take an age to launch/install builds and the Xamarin Android Player, though fast, is still pretty flaky. That left Xamarin.Mac as the only ‘native’ Mac option but there’s a hefty additional licence charge for that (or at least there used to be – I couldn’t quite work out what’s going on with Xamarin.Mac since the Microsoft buyout).

As a result of this tragic state of affairs (remember when Apple used to take x-platform development seriously in the initial OSX days?) I decided the only option would be to ditch Mac native and move to running Windows under VMWare Fusion (at least for any development that requires serious gameplay testing). Quite a change. I’ve done this before for ‘Attack Of Giant Jumping Man’ though so was optimistic that it should be a workable solution, plus I’d have to do the PC port anyway at some point – may as well get on with it.

So I started with a brand new Windows 8.1 VM and a fresh installation of Visual Studio 2015. I’ve been using MonoGame 3.2 up to this point but this was as good a time as any to update to 3.5. Installation of the various components was a breeze. I chose the DesktopGL target as it was most similar to the target I’d worked on for ‘Attack Of Giant Jumping Man’ (so hopefully the few bits of platform-specifc code I’d had to write could be re-used) and it didn’t take too long to get my project to compile. The only problem I ran into was that references to the Microsoft.Xna.Framework.GamerServices namespace couldn’t be resolved. For some reason the reference to the assembly that contains these wasn’t included in the MonoGame template project and had to be added manually (Add Reference->Extensions and then choose the appropriate MonoGame.Framework.Net assembly for the platform you are targeting, its a bit confusing as all the assemblies are named the same in the list so you have to click on each one to see more info).

I’m using the ‘shared folder’ feature of VMWare Fusion to share my source code directory between Mac and Windows – if I import the source files as links then both my Xamarin Studio projects on MacOS and my Visual Studio projects on windows both remain perfectly in sync – nice!

Next step is to import all the content – unfortunately I can’t figure out a way to keep all these files in sync as importing a file as a link from a shared folder doesn’t seem to work in the MonoGame pipeline tool. This is a bit of a bummer but not to much of an issue at the moment – hopefully I can figure something out eventually.

Only issue with the content was that I was getting an error when compiling my custom shader files due to a missing DirectX component (‘d3dcompiler_43.dll’) despite having DirectX 11 installed. I followed the instructions to fix this here (using the second method, not the full install) and all was fine.

So now everything would compile and run. Imagine my joy when, on launching, all I got was the garbage you can see in the GIF on the right. Complete gobbledegook. Spirits totally crushed. What. The. Hell.

I had absolutely no idea what was going on here and no idea where to start debugging. Nothing I thought of initially had any effect. Jetboard Joust runs on MEAT, my own (originally Java-based) 2D gaming platform that has been over ten years in development. MEAT is another layer of abstraction above MonoGame and fairly complex making it difficult to strip things down to MonoGame basics and do a few simple tests but this is clearly what I needed to do.

I decided to run a few simple MEAT tests first and see if I could get anything up and running…

1. Load image and draw sprite
2. Load image and draw sprite with clipping (as if from sprite sheet)
3. Load image and draw sprite with crop (MonoGame ScissorRectangle)
4. Load image, render to offscreen buffer (RenderTarget2D) and then to screen.

…all of these worked fine which was encouraging to an extent but didn’t get me any closer to a solution. However the next test produced some very strange results.

One of the MEAT classes is a graphical font class – a bitmap font and associated metrics data are stored in a single file which can be used to easily render bitmap text to screen. When I tried a test render using one of these graphical fonts the text would appear OK and then mysteriously disappear after around 30 seconds on screen. Bizarre. This mysterious disappearance only happened when my game template code (that handles all the main menus and stuff) had been executed at startup, ie at least 30 seconds before the problem occurred.

So all I could do was to comment out chunks of the game template code, launch the app, and then run a timer for approx 45 seconds to see if the font disappeared – an incredibly tedious process reminiscent of debugging on J2ME handsets. Eventually I narrowed it down to the line of code that was causing the problem – I was reassigning the property originally assigned to the graphical font that was drawn to screen to a different graphical font. Even though this was a mistake on my part there is absolutely nothing ‘wrong’ with this and it wasn’t causing a problem on any other platform. I had to test and retest several times to convince myself that this line of code was the problem but it was – as soon as I didn’t reallocate the property once the font was drawn to screen the test font didn’t disappear and the entire game ran perfectly!

All I can think of is this had something to do with garbage collection of graphics memory. Reallocating the property meant that the garbage collector (incorrectly) thought the memory should be freed which resulted in some kind of graphics meltdown. This would explain why it took around 30 seconds for the problem to appear – it only happened when the garbage collector kicked in. I create the font images using Texture2D.FromStream() rather than the Content.Load() methods in MonoGame which is slightly weird and could be something to do with it as well – I doubt this is as well tested as the Content.Load() methods.

Anyway, one can’t really blame the MonoGame team for missing such an obscure issue and even with the amount of time I wasted over this it was still a pretty fast cross-platform port so kudos to them. Android/iOS to PC in around a day with about 99% of the codebase consistent – not to be sniffed at! Nice to see the issues with the XBox controller fixed in MonoGame 3.5 too!

Dev Time: 1 days
Total Dev Time: approx 32.5 days

previous | next

mockup_3x
Where On Earth Do You Start To Debug This Shit?

Got There In The End – PC, Full Screen, XBox Controller

Jetboard Joust Devlog #29 – To Do’s Are Done

I hate ‘to do’ lists so usually I decide I can’t be arsed ‘to do’ them. There’s something about them that makes me feel like I’m working for ‘the man’ even though I’m sitting in my home office surrounded by synths and guitars with King Gizzard & The Lizard Wizard cranked up to an antisocial volume.

They are useful sometimes though so I do resort to them when I’ve got a lot of boring, fiddly stuff to finish and am having motivation issues. There is something mildly satisfying about crossing items off one by one which is why I always do them on paper – digital ‘to do’ lists are even worse.

So anyway, here’s what’s been on my ‘to do’ list and is now ‘done’. It’s pretty dull but then game development is a lot of the time I’m afraid (sorry to burst your bubble kids, Santa isn’t real either).

Add ‘Brake’ Functionality To Enemy AI
The jetboarding enemies were still kamikaze-ing into the player too often as I was relying on air friction to slow them down which just wasn’t slowing them down quick enough. I’ve given them the ability to air-brake – it’s a bit of a cheat as the player can’t do this without turning round but it looks a lot better.

Make Enemies Drop Ammo
I’m pretty sure it’s going to be too easy to run out of ammo so I’ve added the ability for enemies to drop a small ammo cache when destroyed. Unlike the larger ammo pickup (which completely recharges the current weapon) this one just adds one ‘clip’ of ammo.

Add Pickups And Warp Gates To Scanner
Self explanatory – needed to be done and involved a bit of messing around with class hierarchies.

Improve Rider vs Board Collisions
I felt the way this was working was inconsistent so I’ve added a separate collision check for the rider and the board. A Rider vs rider collision won’t cause any damage the bulk of the time, health is mainly lost when a rider collides with an opposing jetboard.

Add ‘Teleport In’ Effect For Enemies
I was presuming all enemies would be there at the start of each level but after playing ‘Defender’ some more I’ve decided I’m going to need batches of enemies that appear as a level progresses which means I’m going to need some kind of ‘teleport in’ effect. I’m using the same effect I used for the player and wanted to duplicate as little code as possible so, again, needed to mess with the class hierarchies a fair bit to get this to work.

Remove Permanent Enemy Health Displays
I thought this looked a bit dumb when there were lots on enemies on screen so now the enemy health bars automatically show/hide as they take damage. Thankfully this code was already shared with the player and it was just a matter of turning the ‘auto-hide’ feature on.

Add Scanner To HUD
In the code scanner and HUD they were separate which resulted in some stupid duplication of code when switching shaders for the level teleport effect. This is structured much better now.

Fix Scanner Wrap Bugs
Items on the scanner were getting cropped when they crossed the wrap point of the game world. Fixed this by drawing them twice in this scenario at both the left and right of the offscreen image.

Tidy Up Scanner
Changed the way the ‘screen marker’ is positioned as this was overlapping some scanner elements and also fixed an int rounding issue which meant that scanner items with an odd number of pixels in width weren’t getting aligned correctly.

Fix Board Flashing After Player Death
You can see this in some of the previous GIFs – the player’s jetboard was rendering with the ‘collision’ shader when the player continued to get pummeled by bullets after he’d died. I’ve changed this so the jetboard only does this if the player is riding it.

Can’t Collect Pickups After Warp Gates Appear
Dumb bug – fixed!

Carry Last Weapon Over Between Lives
Rather than starting with the default weapon each life.

Weapon Crate Icon Not Showing After New Level
Dumb bug – fixed!

Some Enemy Bullet Trails never Disappear
Dumb bug – fixed! This one was quite a hard one to track down.

And that’s the list all crossed off (for now). Looking forward to actually starting to refine the gameplay!

Dev Time: 1 day
Total Dev Time: approx 31.5 days

previous

mockup_3x
The Improved AI With Braking

mockup_3x
Enemies Now Drop A Small Ammo Cache

mockup_3x
Gameplay Viewed On The Improved Scanner

Jetboard Joust Devlog #28 – Bounty Hunter

So, with those annoying bugs out the way it’s time to start on what will probably be the last pickup – cash!

I want to have some kind of in-game currency for upgrading weapons and the like and I can’t see any point in getting too clever about it so I’m just going to stick with cold, hard cash. Plus I like the retro feel of having big spinning coins that get scattered all over the place – having an enemy dissolve into spinning coins is something of a videogame archetype after all.

The spinning coin wasn’t too hard too get right (at least compared to the spinning crate) but still took me a good couple of hours tweaking. I may well have different sizes of coin so this one, at 12px square, will either be the small or medium. I’m pretty pleased with it though I’m in two minds about whether the way some of the middle pixels flash a bit looks like light reflecting or just looks crap!

Once the coin was done the rest was pretty straightforward implementational stuff – the thing that took the longest was tweaking the particles etc for the ‘got coin’ effect. I also had to add a ‘cash’ element to the HUD.

So now I think I have all core gameplay elements in place really – now I need to start adding some enemies properly and get working on a first playable level. This is also the point where I need to decide if I’m going to do my main gameplay testing on mobile/touchscreen or PC/controller. Or both!

Dev Time: 1 day
Total Dev Time: approx 30.5 days

previous | next

mockup_3x
The Spinning Coin

mockup_3x
Bounty Hunting

mockup_3x
More Bounty Hunting