Some gamedev videos

I have been meaning to record some playthrough videos of my two most recent ‘Week of Awesome’ competition entries and finally got around to it.

The challenge was to make a game from scratch in a week. Four themes are announced, contestants must pick two of those and incorporate them into the game somehow.

I have won 1st prize for two years running with these games:

Invasion Of The Liquid Snatchers – 2017 Entry
Themes chosen were ‘Alien Invasion’ and ‘Chain Reaction’.
I also wrote about the fluid rendering & simuation for this game.


Gamut of Blob – 2016 Entry
Themes chosen were ‘Evolution’ and ‘Shadows’. (sourcecode)


You can also find a video of my 2014 entry ‘Save My Toys’ in an earlier blog entry.


Fluid Rendering with Box2D

This is a technical article about how I implemented the fluid in my game “Invasion of the Liquid Snatchers!” which was my entry for the Week of Awesome 5 gamedev competition.

One of the biggest compliments I’ve received about the game is when people think the fluid simulation is some kind of soft-body physics or a true fluid simulation. But it isn’t!

The simulation is achieved using Box2D doing regular hard-body collisions using lots of little (non-rotating) circle-shaped bodies. The illusion of soft-body particles is achieved in the rendering.

The Rendering Process

Each particle is drawn using a texture of a white circle that is opaque in the center but fades to fully transparent at the circumference:

These are drawn to an RGBA8888 off-screen texture (using a ‘framebuffer’ in OpenGL parlance) and I ‘tint’ to the intended colour of the particle (tinting is something that LibGDX can do out-of-the-box with its default shader).

It is crucial to draw each ball larger than it is represented in Box2D. Physically speaking these balls will not overlap (because it’s a hard-body simulation after all!) yet in the rendering we do need these balls to overlap and blend together.

The blending is non-trivial as there are a few requirements we have to take into account:

  • The RGB colour channels should blend together when particles of different colours overlap.
    • … but we don’t want colours to saturate towards white.
    • … and we don’t want them to darken when we blend with the initially black background colour.
  • The alpha channel should accumulate additively to indicate the ‘strength’ of the liquid at each pixel.

All of that can be achieved in GLES2.0 using this blend technique:

glClearColor(0, 0, 0, 0);

Putting all that together gets us a texture of lots of blurry coloured balls:


Next up, is to contribute this to the main backbuffer as a full-screen quad using a custom shader.

The shader treats the alpha channel of the texture as a ‘potential field’, the higher the value the stronger the field is at that fragment.

The shader compares the strength of the field to a threshold:

  • Where this field strength is strong enough then we will snap the alpha to 1.0 to manifest some liquid.
  • Where the field strength is too weak then we will snap the alpha to 0.0 (or we could just discard the fragment) to avoid drawing anything.

For the final game I went a little further and also included a small window around that threshold to smoothly blend between 0 and 1 in the alpha channel, this softens and effectively anti-aliases the fluid boundary.

Here’s the shader:

varying vec2 v_texCoords;
uniform sampler2D u_texture;

// field values above this are 'inside' the fluid, otherwise we are 'outside'.
const float threshold = 0.6;

// +/- this window around the threshold for a smooth transition around the boundary.
const float window = 0.1;

void main() {
    vec4 col = texture2D(u_texture, v_texCoords);
    float fieldStrength = col.a;
    col.a = smoothstep(threshold - window, threshold + window, fieldStrength);
    gl_FragColor = col;


This gives us a solid edged boundary where pixels are either lit or or not lit by the fluid.
Here is the result after we apply the shader:

Thing are looking a lot more more liquid-like now!

The way this works is that when particles come within close proximity of each other their potential fields start to add up; once the field strength is high enough the shader will start lighting up pixels between the two particles. This gives us the ‘globbing together’ effect which really makes it look like a fluid.

Since the fluid is comprised of thousands of rounded shapes it tends to leave gaps against the straight-edged tilemap. So the full-screen quad is in fact scaled-up to be just a little bit larger than the screen and is draw behind the main scene elements. This helps to ensure that the liquid really fills up any corners and crevices.

Here is the final result:



And that’s all there is for the basic technique behind it!


Extra Niceties

I do a few other subtle tricks which helps to make the fluids feel more believable…

  • Each particle has an age and a current speed. I weight these together into a ‘froth-factor’ value between 0 and 1 that is used to lighten the colour of a particle. This means that younger or faster-moving particles are whiter than older or stationary parts of the fluid. The idea is to allow us to see particles mixing into a larger body of fluid.
  • The stationary ‘wells’ where fluid collects are always a slightly darker shade compared to the fluid particles. This guarantees that we can see the particles ‘mixing’ when they drop into the wells.
  • Magma particles are all different shades of dark red selected randomly at spawn time. This started out as bug where magma and oil particles were being accidentally mixed together but it looked so cool that I decided to make it happen deliberately!
  • When I remove a particle from the simulation it doesn’t just pop out of existence, instead I fade it away. This gets further disguised by the ‘potential field’ shader which makes it look like the fluid drains or shrinks away more naturally. So on the whole the fading is not directly observable.

Performance Optimisations

As mentioned in my post-mortem of the game I had to dedicate some time to make the simulation CPU and Memory performant:

  •  The ‘wells’ that receive the fluid are really just coloured rectangles that “fill up”. They are not simulated. It means I can remove particles from the simulation once they are captured by the wells and just increment the fill-level of the well.
  • If particles slow down below a threshold then they are turned into non-moving static bodies. Statics are not exactly very fluid-like but they perform much better in Box2D than thousands of dynamic bodies because they don’t respond to forces. I also trigger their decay at that point too, so they don’t hang around in this state for long enough for the player to notice.
  • All particles will eventually decay. I set a max lifetime of 20-seconds. This is also to prevent the player from just flooding the level and cheating their way through the game.
  • To keep Java’s Garbage Collector from stalling the gameplay I had to avoid doing memory allocations per-particle where possible. Mainly this is for things like allocating temporary Vector2 objects or Color objects. So I factored these out into singular long-lived instances and just (re)set their state per-particle.

Week of Awesome 5 – Post-Mortem

Well the 5th Week of Awesome Gamedev competition is over! It’s incredible to think that this thing has been running for half a decade.

So the way this competition worked this year is that there are four themes announced at the beginning of the week, which were: Chain Reaction | Alien Invasion | Assassination | Castles.  And each contestant needs to pick two of those and make a game around them, with a week to do so.

My game was “Invasion of The Liquid Snatchers!”.

The Idea

Straight away Chain Reaction and Alien Invasion spoke to me as strong themes that would go well together. I had vague ideas for the other themes too so I spent my 1st day conceptualising ideas for different mixes of themes and trying come up with a viable concept.

In the end I settled on an idea where the game is staged from the perspective of an alien species who are invading Earth to harvest its resources. You play by helping a handful of blue-collar (manual labour) alien minions to undertake the “behind the scenes” activities of an on-going invasion. Activities such as processing Earth’s resources or refuelling a wave of saucerships.

All of this would be driven by the use of the Earth-bound liquid resources that they had been collecting. Water, Magma, Oil and Nuclear Waste were the 4 resources that I settled on. From there I really, really wanted to try and manifest these using a real-time fluid simulation, because that just seemed like a novel and somewhat challenging thing to do – which is exactly the whole point of the gamejam for me: To push myself and do something different.

Each kind of fluid would serve a different function in the game: Water activates hydraulics (raises platforms or opens doors), Oil activates machinery, Nuclear Waste powers saucerships and Magma is supposed to be used by the aliens to forge saucerships.

The chain reaction theme would feature by way of the environment changing in response to these liquids (hydraulic platforms activating or mechanised gears rotating, etc). Most of those changes would be good and allow progression through the level but others would trigger “hazards in the workplace” such as having a row of missiles lined up to fall like dominos that end up crushing your minions!

What Went Well?

Let’s see…

  • Time – I had the week off work. Never done that for previous years where I’ve always worked during the week. So this year I had a lot more free-time in comparison. I didn’t spend it all programming mind you, but it was just nice to not have to hold down the day-job and then spend my evenings coding as well!
  • Existing code-base – From the previous two times I have competed I have built up a thin framework over the top of LibGDX which really helps me hit the ground running. Mostly it’s just resource caches for textures/sounds/etc and some ‘fix your timestep’ gameloop stuff. Nothing too fancy.
  • Shaders – My fluid simulation is rendered using a custom shader. I’m no shader expert having written a merely a handful of simple shaders in my time.Shaders cause(d) other people a lot of agro where their games don’t work on other GPUs, etc. For that alone I tend to avoid them generally. But this year I couldn’t, not for the fluid anyway. Fortunately I had very few issues with the shader authoring. I’ll write a bit more about how the fluid sim works in a follow up technical post.
  • Audio – I was able to find online several soundbite recordings of water sloshing around (each 0-2 seconds long). I picked several that sounded good and classified them into two sets: One for water being emitted and one for water being collected. Then to create the seamless sound of running liquid I select a sound snippet at random every 1 or 2 seconds and play it with sufficient falloff and overlap with the previous snippet while also making sure to never play the same sound twice in a row because humans are too good at noticing repeating patterns. It sounded pretty bad at first but after a but of tuning I’m quite pleased with the end result.
  • Art(?!) – As I say every year: I don’t attribute myself with much of any digital graphics design skills and I’m colour-blind which is a huge pain in the ass for this sort of thing. So I try to mask my artistic failings with code. But I surprised myself with the art work this year, it kind of works I think?! For the first time this is ALL my own art work, I didn’t take anything from the interwebs, I just used Paint.Net and a lot of it is drawn free-hand with the mouse.

What Went ‘Not So’ Well?

  • Liquid CPU performance – To begin with I simply assumed that performance wasn’t going be an issue in my little old game. I was wrong. It took some ingenuity to prevent the sim from becoming a bottleneck. Fortunately I have a copy of JProfiler which is my favourite profiler for finding performance hotspots. I’ll write more about that in the follow up post about the fluid rendering.
  • Level creation – In previous years I would implement an ASCII-based level format that gives a reasonable-ish approximation of how the level will look on-screen. The idea works ok for purely grid-based worlds but it doesn’t scale very well with multiple layers or when things are not grid-aligned. So this year I spent some time mid-way through the week to write a crappy in-game interactive level editor. Even with that I found it very hard to create engaging levels. And since my game is heavily physics-oriented I had to account for all sorts of “physics bullshit” in order to get each level to a point where it is deterministically solvable by the player and not just a big mess of physics stuff that may or may-not play out.
  • Box2D Determinism – It is my belief that Box2D is supposed to be deterministic (as long as the input is the same and the timestep is fixed – which it is). Yet I am definitely seeing slight variation from run-to-run. So I can’t explain that yet. I need to investigate what the ‘f’ is going on there. For this time around I just decoded to design around the problem.

Reception So Far…

So far I have had very positive reviews. First and foremost I’m very pleased to hear that people enjoyed the game.

Many/most of the criticisms I’ve received are about things which I completely agree with too, so no surprises there. I would definitely have fixed them where this not a week-long development. There’s just not time to do everything unfortunately.

It’s not known yet how all the judges feel as that still remains to be seen.

Riuthamus (one of the judges) live-streamed his play-through of my game on Twitch. It was hilarious! He actually found some pretty decent ‘alternative’ ways of solving one or two of the levels that looks to me every bit as good as my intended solution. So that’s fine by me! It was great fun to watch and valuable feedback too.

So How Does That Fluid Simulation Work Anyway?

One of the biggest compliments I’ve had is when people think the fluid simulation is a soft-body physics or a true fluid simulation. It’s really not 😛

I’ve decided to write up a technical article about the fluid simulation and rendering process which you can find over here.

That’s A Wrap!

I had good fun over the week and just want to extend a big thanks to the competition organiser (slicer4ever), to the other judges and to the prize-pool contributors.  They have all done a fantastic job at making this competition happen! Every year I see the competition evolve in very positive ways!

And good luck to all the contestants!

Week of Awesome IV – Gamut of Blob – Postmortem

Embarrassingly I haven’t used this blog in 2 years and that was for my WoA2 postmortem!

Well WoA4 is over and I am super pleased with my entry. It is somehow more complete and polished than I had anticipated to achieve considering I had a full week of work and a couple of weekend commitments that would see me Macbook-bound for the majority of the weekend.

This year announced 4 themes and contestants were expected to select and incorporate 2 of these for their game: Shadows, Evolution, Ruins, Undead.

A restriction was that Shadows and Evolution had to manifest as gameplay mechanics, whilst Ruins and Undead would need to manifest as graphical theming. Since I am no artist, it takes me a long time to produce art and I have no experience producing art of any kind on a Mac, I decided to opt for the 2 gameplay themes: Shadows & Evolution.

Scope is always an issue in any project. So I took the entire Monday just to let the themes sink in and try to come up with an idea that was appropriate in scope for the free-time I had. I was open to extremely simple games like Flappy Bird but I simply could not marry that up with the requisite themes (evolution, shadows, ruins, undead) in a way that enthused me. Also under consideration was a farming game where veggies are bred and transmuted to achieve a desired phenotype with a supply & demand mechanic driving that, as well as some kind of underwater game like flOw. Both interesting ideas but were too ambitious.

The idea I went with was top-down maze-puzzler with minimalist graphical look featuring cute little blob creatures. Gameplay-wise I was partially inspired by games like Chronotron or the Clank levels from Ratchet & Clank: A Crack in Time. In these games there is a way to generate multiple versions of yourself which must collaborate together to finish the level, things like standing on buttons to open gates. While I did not include their time-travelling mechanic I do have lots of cute little blob creatures running around standing on switches to banish shadows and allow fellow blobs to progress. Blobs can replicate themselves by finding DNA/gene fragments in the level; picking these up will spawn an evolved blob friend, each blob colour has a unique skill which allows it to access parts of the map that your regular unevolved green blob is unable to reach.

day6 (3pm)

The great thing about this idea is that it scales up/down depending on how productive I am: If things go well I can always develop new types of blob which enables new gameplay elements. If things go slowly then I can scale back on my ambitions for lots of different kinds of blob and focus up on just getting *something* done. My original plan included 5 types of blob:

  • Green – The standard unevolved blob
  • Blue – Able to swim and pass through water.
  • Red – Tolerant to extreme temperatures and can walk over lava.
  • Purple – Resistant to the genetic stresses of teleportation and can use teleport pads.
  • Yellow – Speedy, takes long straight paths very quickly and does not stop until it hits a wall.

I probably could have implemented all of these if I had sacrificed some polish but I didn’t want to do that.  In the end I managed all but the Yellow blob, not bad at all! And I don’t feel that the game has suffered at all.

One of the hard-learned lessons from previous years was that starting from a position of no code (just an empty main() method) is tough going. I end up spending a good 2-3 days just knocking out basic infrastructure (resource management, game-states, sprite-rendering, audio, physics, etc). So this year I prepped a very light-weight game-agnostic framework based on LibGDX to handle all that. This was a massive productivity boon and this ‘engine’ wasn’t at all constraining either having received only a minimal amount of frantic hack’n’slash near the end, which I will probably refactor and generalise for the future!

Something that didn’t work out as well I had hoped was the level file format. I used a similar format to my WoA2 game which worked very well for that game. However this time around I had lots of layers to the map and keeping them in-sync was an error-prone head-ache. Some kind of level-editor would have gone a long way to ameliorating this but there wasn’t time for that kind of development. Perhaps for next time I can generalise the concept of a tile-based level editor? Or learn to use an existing one and write an importer for its file format.

Overall, as usual, it was a lot of fun. Very tiring. But a lot of fun.

I have whizzed through playing the other contestants’ games (need to go back and play some of them for longer) and I have to say that I really do not have a good sense for where my game will place amongst them once the judging is over. As usual I am blown away by what people are able to achieve in a week!

Congratulations to everybody who managed to submit an entry. I am looking forward to next year’s competition already! 😉

Save My Toys: A Walkthrough (Week of Awesome II)

First off I am delighted to have placed 5th in the competition overall!

Due to the great response I’ve had to the game, from other competitors and the judges I have decided to record a quick playthrough of my Week of Awesome II competition entry: Save My Toys.

The video quality is bit low but this shows the full extent of the game and the solutions I originally envisaged – although some levels have multiple solutions either by design or not quite intentionally.


My “Week of Awesome” Competition Entry: Post-Mortem

So it’s been a while since I last posted but here I am writing a new entry!

The other week I competed in the unofficial ‘The Week of Awesome’ game development competition. The idea is you’re given a week to develop a game and the game must fit a theme which is only announced at the very start of the competition. The theme was: “What if Dinosaurs hadn’t gone extinct?” There were various takes on the theme, all of them were good ideas.

My take on it was that the dinosaurs didn’t go extinct because, after the meteorite hit, they came back to ‘life’ as zombies. Clearly then the hordes of dinos romping around are the bad guys. To bring a good-guy into the mix (and therefore the player)  I settled on the idea of Granny who was on her way out to the Bingo but is highly inconvenienced by the zombie dinosaurs; hence her reason for kicking some zombie-dino butt.

For anyone looking to download my entry, you can download it here: Granny v.s. Zombie Dinosaurs. You’ll need at least Java 6 to run it.


The first thing I did was to plan the game. I don’t think you have to plan every aspect of something before you start coding. I’m a strong believer that requirements can rarely be gathered in full in advance and they will change once the thing begins to take shape and new & improved ideas begin to form in peoples’ mind. Maintaining a level of agility is important and, let’s face it, we’ve only got a week to develop a game. Analysis paralysis is something to be avoided.

Granny v.s. Zombie Dinosaurs - Planning 1

My planning involved sketching ideas down in a notebook. I already knew I wanted to do a 2D side-scroller with zombie dinos coming in from both sides of the screen so it was really the case of fleshing that out a bit:

  • What would the dinosaurs look like?
  • What would the main character be and look like?
  • What would the world look like?
  • Miscellaneous things: Weapons, pickups, etc

Granny v.s. Zombie Dinosaurs - Planning 2

One of the key things for me was to play to my strengths: I am a good programmer. I am somewhat creative and artistic but I am NOT an artist. I know nothing about making music, sound effects or animation. Sophisticated artwork would take time to produce; waste time even! The game needed simple graphics that could be produced quickly. Which means they either need to be abstract shapes that can be rendered by code, or they need to be simple sprites that I can knock together quickly in Paint. Since we’re talking dinosaurs rather than just squares and circles, I opted for the latter. I’ve always liked the idea of making a monochrome game, just two colours. Like as if you’re playing as silhouettes. So I thought I would test that out somewhat with this: White on Black. That would play nicely with my goal of simple graphics as there would be very little detail within each sprite.


In keeping with the goal of playing to my strengths I opted to use Java for the development language. I use it everyday at work, so my present state of familiarity with the language is very high. For the graphics I chose LibGDX, which is a framework I dabbled with once before and it imparted a good impression. In fact, they have a swanky looking website now, so it’s obviously doing well. Turned out that 4, if not more, of the other entries also used libGDX so it must be gaining traction.

Since I was doing a 2D game I decided to stick to libGDX’s 2D framework, which is a high-level abstraction over OpenGL in the form of textures, sprites and batched-rendering. It’s easy to use, which is the important thing.

I wanted to have non-flat ground and I wanted Granny to be able to jump. This meant I needed at least rudimentary physics for gravity and ground collisions. Throw in the requirement to track collisions between Granny and dinosaurs (for them to inflict damage) and between Granny’s bullets and the dinosaurs – and I decided to just go right ahead and integrate Box2D (of which libGDX includes a JNI wrapper) to handle the collision detection and entity movement.

Granny v.s. Zombie Dinosaurs - Day-4I posted almost-daily progress updates on the GDNet forum topic, which included screenshots. The important thing was to stay focused; to always have it clear in mind what feature I’m implementing currently and which features I wanted to pick off next of all. Such as today I’m all about integrating physics, or today I want a highscrores table and improved blood, etc.

I made the deliberate decision not to worry too much about the code health as I won’t be maintaining it long-term. There are various devices in software engineering that slow down the short-term development in favor of improved maintenance and development costs in the long term. Things like coming up with a perfect abstraction and removing duplicate code, etc. By not doing these things you accrue technical debt that must be paid off later on, but if there is no “later on” then it’s a no-brainer that getting shit done fast is a Good Thing ™, especially for a competition. As a result I have plenty of duplicate code. Rather than trying to common-up the granny entity with the dino entity, I just have two classes: Granny and Dino. Both of these do a lot of the same stuff. I could have created an abstract base class for them both, but I was worried that I would need to slap in hacks at the final second and by having them share code would make that kind of thing harder to do.

I had it fairly well defined in my head that the World, Granny, Dino, Bullet, etc classes where “the model” from a traditional MVC architecture. I had a renderer that was obviously the view; it maintained all the sprite information and used the data from the model to paint the scene, quite literally something like: renderer.draw(world); I also had a WorldEvents class, which kind of acted like the controller. It would receive events from the input mapper, from physics collisions and from the World itself. Its job was to decide how to influence the model based on those events.

What I was less sure about – and still am – is about my handling of the simulation. For whatever reason I decided to couple it very tightly with the model. Most entity classes had a Box2D Body data member within them. The physics engine itself was hosted inside the World class and even besides physics, various bits of game logic such as dino spawning where handled by the World in its update() method. …Possibly all of that should have been extracted from the model… In which case the various entity classes would hold their own positional data and some external update loop would synchronize that with Box2D while also use public methods on the World to periodically spawn Dinos, etc. I think perhaps by coupling them together it simplified and sped-up the development for this game, but for a longer-term project separating the model from the simulation would be a good choice.

Sound effects where another big thing in this game. I only use 3 audio files, one of those is the background music. This was all done on the final day so it does look a bit hacked in. I had never implemented sound before so it was a cool experience. LibGDX makes it very straightforward affair. I know from perusing the DirectX audio documentation in the past that sound can be a complex matter but LibGDX cuts all the crap and has only a basic API that was all I needed. One of the interesting thing about audio (at least in libGDX) is that unlike most other things it’s a fire-and-forget type resource. You don’t have to advance through the sound frame by frame like you do with animation, or keep hold of any handles (you can, but it’s optional). You simply invoke the non-blocking play() method and it just begins to play. So it was an absolute breeze!

What went well?

A lot of it went well, I was fortunate really:

Spare Time – I had much more free time than I expected to get initially. Most of this allowed for better polishing.

LibGDX – A very pleasant framework to use. The only gotcha is that it’s high-level and even where it exposes just a simple JNI wrapper (e.g. around Box2D) there are no guarantees that it’s 100% complete. But if you don’t necessarily need all the bells and whistles then it’s a perfect choice for a Java media library.

Box2D – It is really easy to use and paid dividends in speeding up development. Initially I began to implement my own simplified physics for jumping but when I began to consider bullets firing, inter-entity collisions, blood splats, etc, I decided that Box2D would be a smarter choice. It took about a day to integrate whereas it would probably have taken me 2 days to implement all the physical interactions in my own code and fix all the ensuing bugs. When it came to implementing blood it took me mere moments to get a basic implementation up and running!

LibGDX also comes with a debug-renderer for Box2D, it is worth its weight in gold, so get that running early on! Being able to see visually how the physics is behaving relative to your own visuals is incredibly helpful and helped me nail tons of bugs much faster than I otherwise would have.

Granny v.s. Zombie Dinosaurs - CutsceneArt-style – Using paint for all the artwork (and Paint.Net to apply alpha) made for a unique visual style, almost like an animated Paint drawing. In the end I quite like it. It won’t win an awards for artistry but it hangs together well. Much better than mis-mashed images stolen of the internet would have. Or if I’d tried to actually do a good job at the artwork 😛

Animation – Bringing things to life is important. Static sprites sliding around just looks rubbish. It was pretty easy to add walking feet. I just tween across a sine-wave to create the swinging motion of the dinosaur’s feet and the up-down motion of Granny when she walks. If I had more time I would have animated her walking stick and the jaws of the dinosaurs.

GameStates – GameStates are full-screen states that the game can be in at any one time. For example there’s a game-state for actually playing the game, a game-state for the high-scores table, for the start-screen, etc. They can decide when to transition from one state to another, in effect it’s an FSM. I had heard about people implementing game-states like this before but wasn’t sure how well it would work out – turned out great for me. It made adding new features like the high-scores table really easy.

Granny v.s. Zombie Dinosaurs - SignpostsThe only state that is a bit iffy is the sign-reading state. Probably this shouldn’t be a state at all, just a boolean within the in-game game-state; I got it to work this way though, which just goes to demonstate the flexibility of the system. In fact it acts like a stacked state, it first renders the in-game game-state before rendering itself. I knew this would be the only stacked state though so I didn’t implement any generic handling of stacked game-states, I just had the sign-reading state handle it on its own.

I actually recently wrote about the game-state system on the GDNet forums.

Focusing on the scoring criteria – There were 5 criteria each marked out of 20: Graphics, Audio, Gameplay/fun-factor, First time user experience and Theme. I aimed to keep my graphics simple and the audio I decided just had to be simple and sensible to work well. The gameplay/fun-factor was always going to be a challenge, making something really fun involves a surprising amount of work and time but I decided that you can’t go wrong with a game that involves shooting things that squirt blood.

The first-time user experience is something I thought a lot of other entries might lack so I decided to try and win some points in this area by adding a cutscene at the start, comical in-game help along the way with the use of sign-posts and also a highscores table with humorous entries in and also a guaranteed position on the leaderboard for the first-time play through (i.e. 7 out of a maximum of 8 entries were pre-populated).

What went wrong?

Well, a number of things:

Being too ambitious – Partly this was deliberate, I wanted to use the competition as an excuse to play with graphics, physics and audio. It did mean it really took over my life for a week though and I was up against the clock at the end.

Co-ordinate systems – I should have nailed this one down early on really, but I didn’t. There are a few coordinate systems in-play within the game: Box2D has one on the scale of real-world objects (meters), the renderer has another one defined just as a scaling of the coordinate system used by Box2d in order to render it. The renderer also has regular screen-space coordinates (pixels) that is used for drawing the full-screen backgrounds as well as applying multi-part sprite offsets (e.g. for the legs relative to the body). None of that code is particularly well encapsulated and it was always a bit of a headache to remember which one I’m using for what and how to convert between them all.

Separating entity representations – The physical properties of an entity are held in one place, the rendering properties in another. They’re actually quite related values though; if an entity is physically larger the it should also be rendered bigger, right? It’s nice in some ways to keep them separate but it was a pain at crunch time to keep those values in sync. What I should have had is an abstract representation and the physical & visual properties be calculated from those. Arguably that might have been more work.

Floor/Terrain – This didn’t go wrong so much as it didn’t pan out to be as awesome as I initially envisioned. I had planned that there would be multiple routes through the game e.g. a high route and low route, done using foreground and background terrain as well as platforms which would further emphasise Granny’s jumping ability and add an extra dimension to the player’s decision-making which, as it stands, is pretty limited to just which dino to target next.

Granny v.s. Zombie Dinosaurs - In-gameIn the end I only had time to implement a basic continuous height-mapped terrain system. I did however make it infinitely auto-generate by selecting randomly from a set of a pre-made level-segments each with differing probabilities. I only had time to create 3 level-segments though: A flat segment, a step-up/step-down segment (see screenshot) and a hill. The camera also won’t follow Granny vertically so the useful height was effectively  constrained to about 5 units, when combined with the limitation that the terrain be continuous it pretty much  limits the amount of creativity possible when designing terrain segments.

Level Balancing – I didn’t get to spend as much time on this as I would have liked, in fact I only spent about a half hour on the run-up to the end of the contest configuring the gameplay difficultly and how that changes as you progress. This is definitely something I should have been more on-top of.

I implemented the concepts of Levels, which are actually demarcated by the signposts but I purposely didn’t want an overly explicit level counter, just continuous gameplay. As the player reaches each level the settings are adjusted to control how frequently the dinosaurs spawn from either side, which dinosaurs will spawn (and the likelihood of spawning any given type of dino), which floor segments will be used  to auto-generate the terrain (and again to what likelihood) and the frequency of spawning ammo-pickups. I managed to define about 7 levels (with the final level being a never-ending one) that gradually introduce more complex terrain, more kinds of dinosaur, more frequently spawning dinos and all the while have the signposts introduce the new content as the player progresses.

It worked out okay but it was sheer fluke that my level-balancing was as good as it turned out. That said, it seems like you cannot progress past about level 5 when the stegosaurus are introduced since I simply don’t provide enough ammo to take them all out. Fortunately, by that point, all the game’s content is introduced except for a couple of non-helpful, comedic sign-posts; the remaining levels are just about making things harder. But at least you get to see everything the game has to offer, by and large.

As a final point, Granny has health, but I didn’t have time to add health-pickups so she’ll only ever get more and more unwell, poor Granny.

Other Lessons

Besides those that have been mentioned above I learnt (or “learned” – crazy irregular verbs) a few good lessons during development. Mostly these were about peculiarities of Box2D and/or LibGDX as these were essentially new tech to me.

Always cpy() your Vector2s – It turns out that Vector2’s in LibGDX are mutable little devils. Presumably this is done as an optimisation. Nevertheless it caught me by surpise a number of times. Consequently if returning a Vector2 from a function, or accepting one as a parameter: Always make a copy! This is actually good general advice whenever you accept a mutable value that you intend to own. Last thing you want is for it be changed under your feet!

My worst experience with this was when I was returning Vector2’s from a Box2D body and forgetting to make a copy (in fact you might have thought LibGDX’s wrapper would do that; it isn’t clear whether mutating this object is actually safe and if it would correctly modify the body’s physical property). Consequently when the body was destroyed it left a now-dangling Vector2 held some place else that would crash the JVM once touched. Tracking that back to a missing cpy() was more guesswork than scientific debugging.

Defer your deletes – This one kind of depends on how your architect things. For me the various entities exposed details such as their position and velocity, but these were just being passed straight out from the underlying Box2D bodies. So, say a dino was killed by a bullet impact. I would remove the dino from the World, which would also destroy the Box2D body. It appears that Box2D immediately frees the resource (it doesn’t wait for the next tick, for example). The problem is what if you wanted to spawn some blood from the dino’s position? You can’t if you kill him first. Obviously you could spawn the blood and then kill him (and maybe, for blood, that makes sense) but it’s a little on the brittle side and a leaky abstraction – The dino-to-bullet collision handler is just telling the world that the dino is dead; if it has to know that the dino will also become invalidated then it undesirably knows something about the implementation that I would have preferred to keep hidden.

Another issue is when multiple collision handlers are invoked by Box2D. One of my more serious and bugs was an occasional crash that only began to appear after I introduced multiple dinos. It turned out that a bullet could collide with multiple dinos at once. This is obvious in hindsight – the bullet isn’t infinitely tiny like a raycast, it’s a circle with an area being simulated by Box2D. If both those dinos happened to die from that bullet impact then one of those collision handlers is dealing with an already-deleted Body and badness ensues.

This was all fixed by buffering all deletes up inside of my own Box2D World wrapper. Multiple deletes were de-duped by storing them in a HashSet container. At the next tick I would then run through and do all the deferred removals for that frame. Now those bodies would remain valid for the entire frame and I could go back to forgetting about memory management issues 😉

Finding free assets is hard – By far the hardest asset to acquire was the font. It’s called DINk. Many “free” fonts have uncertain licenses, I’m sure the owners intend them to be wholly free but unless they give clear licensing terms then I am uneasy going near them. Many other fonts are free for virtually any purpose but may not be redistributed. Lack of redistribution is a massive bummer because that is exactly what I need to do – package it as an asset and redistribute it as part of my game. Most of the font licenses I found were around the idea that a font is used in subset to create a document and that document is about the only derived work that can be created from that font. I did my best to acknowledge all the asset authors in the ReadMe, as well as being clear about what the licenses are.


Overall it was really fun. I hope they do another one as I’ll surely participate. I think I’ve learned a few lessons for this one though: It was too ambitious to truly finish and sucked up far too much time. I think a much simpler game could fair just as well. Using the competition as an excuse to play with new tech is quite fun though – Maybe next time I’ll play with shaders; perhaps some kind of game involving making things glow or somehow involving the lighting such having to stay hidden in the shadows. I have already expressed an interest in another competition, this one initiated by one of the judges and the goal is to make some flavour of a Pong clone – could be quite cool!

I shall post this post-mortem to the forums when all the judging is complete – I think that pointing out the flaws in my game whilst the judging is still underway would be unwise 😛

If you want to see what kind of twisted, scary code and sheer quantity of magic numbers that went into making this game, I have open-sourced it on GitHub:

In closing I would also like to thank those who voted for my game in the Peoples’ Choice Award, which I am delighted to have won.

I look forward to seeing what the final verdict was from the judges!