Category Archives: Uncategorized

Jetboard Joust Devlog #59 – Alpha Launch!

Woohoo – major milestone alert!!

I’ve finally got things to the state where I feel like I can release a playable alpha. Yes, there are still a few bugs and things I need to refine in the game design but I think we’re pretty much there. What’s also great is, thanks to the great flexibility of MonoGame, I can also release a MacOS version. The MacOS port only took me just over a day and I may detail that in another post.

For those of you who just want to cut to the chase and download the thing click here!

And for those of you who are actually interested in the devlog here’s a list of the significant additions in this final round of tweaks, many thanks to the folks who gave me feedback at the pre-alpha stage…

Pistol Range
It became obvious from user feedback that the range on the pistol (the default weapon) simply wasn’t enough. Players found they had to get unnaturally close to enemies to kill them which often meant they crashed into them by accident. Consequently I have increased the initial range of the pistol by about 75%, though to compensate I have made the damage done tail off as the bullet reaches the end of its range.

Its better than it was but I’m not convinced I’ve yet solved this issue. It’s a bit of a delicate balancing act as I want the weapon to be meaningfully upgradeable, yet also powerful enough to start with and not overpowered later on. Also, because the enemies use identical weapons to the player increasing a weapon’s range/damage also increases the difficulty of those enemies that use it!

Another more radical solution I’m considering is to significantly increase the pistol’s range yet further (and maybe give it unlimited ammo) yet not allow it to be upgraded. This would make the start of the game considerably more approachable for new players and increase its difficulty later on as players wouldn’t have a strong default weapon to fall back on. It would also put more emphasis on managing ammo levels later in the game which could be a good thing.

Playing Catch
It has always been a feature of the game that catching an enemy’s jetboard before it hits the ground give both an ammo and a shield boost and is therefore preferable to waiting until it hits the ground (generating only one type of pickup). I didn’t feel this was very clear though so I have added mini shield/ammo icons to the enemy jetboards as they fall which will hopefully communicate that there’s goodies on board and these things are worth collecting. The player also gets a ‘nice catch’ message if they do this indicating that it’s a good thing to do (catching jetboards is also the way to unlock new weapons)!

Extra Life / Jetsuit Indicators
Picking up your abandoned jetsuit after you lose a life is a central game mechanic as it’s the way to recover lost cash and not lose out on valuable upgrades. Similarly extra lives in the game are pretty rare so when they do appear the player isn’t going to want to miss out on them. I talked about adding pickup indicators and detectors for other bonus items here and decided I had to do the same for jetsuits and extra lives as they are arguably the most valuable pickups in the game!

Microsite
Yeah, not really part of the game dev but I thought I’d include it anyway. I needed a microsite or landing page to distribute the alpha so went ahead and built one. I’ve included a simple signup for for a mailchimp list. Goodness knows whether anyone will use it but hopefully it’ll server some purpose.

Update Tracking
I’ve added a very simple way for the game to poll the web server, check whether an optional or mandatory update is available and notify the player appropriately. The alpha build will also expire after a set date (currently the end of June so plenty of time to play).

I may now take a break from gamedev for a bit as I have had to take on some appdev contract work (fortunately a pretty nice project) to top up my dwindling coffers. I will have to try and get a youtube promo done over the next few weeks though, and hopefully get the word out about the alpha.

Thanks for watching and please stay tuned…

Dev Time: 4 days (inc microsite build)
Total Dev Time: approx 115.5 days

previous

mockup_3x
Making It More Obvious That There’s Booty On Falling Jetboards

mockup_3x
Pointing Out The Player’s Abandoned Jetsuit


You Don’t Want To Miss Out On An Extra Life Either!
Advertisements

Jetboard Joust Devlog #58 – Almost At Alpha!

So for the last couple of days or so I’ve been doing an awful lot of playtesting and making what should be the final round of tweaks, improvements and bugfixes for the playable alpha. A large amount of this has been general tweaks to difficulty levels and the like which would be too numerous to list here but here’s a few specifics as to what’s been included…

Weapon Stashing
In order to prevent the player from overpowering one weapon and simply sticking with that I now switch to the default weapon on losing a life and completing a level. This isn’t such a big deal at the moment as there are only three weapons but there will be a lot more in the final game. In addition to this, weapons are no longer automatically reloaded when ‘swapped out’ meaning it’s possible to stash an empty weapon. As a consequence I’ve also made weapon crates display the amount of ammo in the included weapon. Stashed weapons retain their ammo between levels.

Controls
I’ve tweaked the controls a bit so that they are a bit less ‘binary’ and it’s easier for the player to make smaller movements. There’s a fine line here between being able to make subtle movements and being able to move quickly when necessary. I’ve moved to using lerp-based interpolation for the player’s vertical speed and also added the ability to ‘brake’ (cancel horizontal motion) by pulling directly down on the controller.

Camera
Slight improvements to make the camera track better when running away from enemies (ie not track as if you’re trying to attack an enemy that’s behind you). Again there’s a fine line here as sometimes you are ‘dogfighting’ with an enemy that’s behind you so what I do is make a decision based on how long the player has been moving in the same direction. Rapid changes of movement tend to mean dogfighting, continuous movement tends to mean running away!

Input And UI Labelling
I’ve checked all the dialog buttons in the game for keyboard and controller input and labelled them appropriately depending on the input method being used. If the game receives any controller input I presume the player is playing with a controller, otherwise I assume a keyboard is being used. I’ve also made dialog buttons and a few other UI elements respond to mouse input just for a ‘belt and braces’ approach. the game itself can’t be played with a mouse though.

Instructions
I’ve added some pretty minimal (but hopefully sufficient) instructions and a diagram of controls for both keyboard and controller input.

Enemy Randomizer
I’ve made yet more tweaks to the code that generates the levels so there’s a much better distribution of enemies. I’ve added a ‘Config’ class that contains all the definitions for enemy/weapon intro levels and difficulty settings in one place so it’s much easier to edit.

Baiters/Bastards
These are the enemies that appear when the player is taking too long to complete a level. Originally I had it so they didn’t need to be destroyed in order to complete a level (as in Defender) but I thought it was a bit weird getting the ‘all enemies destroyed’ message when there were enemies still present. Now the baiters have to be destroyed too but no additional baiters will appear once all other enemies have been defeated.

Bugfixes
Fixed a bunch, one of the most amusing ones was where an enemy’s jetboard would continue to fire after the enemy had been killed (if it was armed with an automatic weapon). This was funny but I couldn’t leave it in.

Now I have to decide whether I’m going to create a proper installer for the alpha (and build it if so) or just distribute a zip file – then you should be able to have a go!

Dev Time: 2.5 days
Total Dev Time: approx 111.5 days

previous|next

mockup_3x
Weapon Crates Now Display The Amount Of Ammo Inside

mockup_3x
Alpha Instructions

Jetboard Joust Devlog #53 – Camera Obscura

In the unlikely event that you’ve been reading this blog from the beginning you might remember that the camera in Jetboard Joust has always been something of a bugbear for me.

Way back in the early stages of development I wasted countless hours trying to get a camera action that I was happy with but, after failing miserably (once I started to add enemies the camera tracking solution I described in the blog post above proved woefully inadequate), decided to go for the simplest solution of locking the camera to the player centre-screen and leaving it at that.

Thing is – this kind of worked. Maybe because the camera is horizontal-only and the player’s horizontal motion smoothly accelerates and decelerates with no sudden changes? The game was perfectly playable and there were no sudden camera movements that looked out of place or anything.

But… it was just a bit boring and I always thought I could make it better, so as I’m nearing ‘playable alpha’ stage I decide once more to revisit. I set up a separate ‘Camera’ class (rather than putting all the camera code in the main game class as I had before) and attempted to approach things a bit more methodically.

Though it probably seems blindingly obvious I had a bit of an epiphany on realising that camera motion is really comprised of two separate elements, the camera target (ie what you want to be the centre of attention) and the way the camera moves to that target.

I decided to tackle the camera motion itself first. Many online articles talk about Lerp smoothing as the de-facto way to deal with this so this seemed a good place to start. Rather than working with Lerp smoothing on the camera right away I tried applying it to some sprite motion so it was much easier to see what was going on. The results of this really require a separate post so I’ve explained the process in a small tutorial with some example code here. The net result was an extended Lerp class that moves an object smoothly towards a target no matter how often (and by how much) the target position changes.

Now I had a way of making the camera track smoothly I set about working on the camera target (what the camera is moving towards). This was a lot harder! My thought process here had three key stages…

1. Player Velocity
One of my main concerns about the camera being centred all the time was that, if the player was moving quickly, lookahead was limited to half the screen width. In ‘Defender’ (the main inspiration for Jetboard Joust) the camera seems to be focussed something like 25% of the screen width if front of the player so I started with similar approach. I took a maximum lookahead value, worked out the player’s current velocity relative to the maximum possible velocity, and then placed the camera target the same proportion of the maximum lookahead value in front of the player.

The end result was OK but, as it doesn’t take long for the player to accelerate to top speed, the camera was moving far too quickly to its farthest position. Jetboard Joust plays differently to Defender in that there is more ‘dogfighting’ style gameplay when dealing with enemies (rather than hurtling in one direction as fast as possible) and somehow the camera movement needed to reflect this. So I tried a different approach…

2. Directional Duration
For my second attempt I set up a variable that gradually increased/decreased in value depending on how long the player was travelling in a particular direction. So, from stationary, if the player was travelling left it would take approx five seconds for the value to reach -1.0 (the minimum possible) and the inverse for travelling right. I then multiplied the maximum lookahead value by this variable and set the camera target appropriately. If the player changes direction I set the variable to zero for a quick turnaround.

This worked much better than my first attempt – the camera seemed to track fairly naturally with a long lookahead distance if the player was travelling any distance left and right and not switching erratically in the midst of battle. There were a couple of problems with this approach though, I didn’t like the obvious lag as the camera tried to ‘catch up’ with the player when accelerating from stationary and too often I’d end up forced to do battle at the edges of the screen.

3. Enemy Location
For my third attempt I adopted an entirely different tactic. I totally ignored player movement and instead positioned the camera entirely based on the location of nearby enemies (limiting this at a maximum value to ensure the player remains onscreen). I tried two approaches here:

3a. Enemy Position
Firstly I tried positioning based on how many enemies were to the left or right of the player. So I’d start by dividing 1.0 by the number of enemies within range and then adding or subtracting this number to a variable based on whether each enemy was to the left or right of the player. The result was a number between -1.0 and 1.0 which gave an indication of where the action was relative to the player – this number was multiplied by the max lookahead value to give the camera target position.

This strategy had some interesting results in the way the camera swung towards the action but overall it was too unreliable, I’d often find my attention was on a particular enemy and the camera would suddenly swing away as there were more enemies behind me or something. So I tried something simpler…

3b. Closest Enemy
This time, based on the logic that 99% of the time the closest enemy would be the one the player was concentrating on in a dogfight I simply targeted the camera at the closest enemy to the player (whilst ensuring the player remained onscreen).

The result of this was strangely compelling! Although the camera lurched left and right far too much it made the gameplay seem more intense, dynamic, and somehow just more ‘fun’. I was really surprised about how much the gameplay was enhanced by this simple approach – I just needed to find a way to tone it down a bit.

4. All Of The Above
So what I did next was use all of the above approaches and apply a weighting to each of them, hoping that this would provide some kind of ‘happy medium’. Fortunately, with a bit of tweaking, it did!

I still felt I could improve things further though so I made this weighting dynamic. I fixed the weighting based on player velocity at 25% and based the remaining 75% on either the closest enemy (if any enemies are within range) or the directional duration.

Another tweak I made was to slightly bias the ‘closest enemy’ calculation based on the direction the player is facing so that enemies in front of the player are considered ‘closer’ (I reduce the distance by 75%) than those behind. This makes the camera more likely to stick on enemy the player is currently engaged with.

The result is a camera that doesn’t lag, gives a long lookahead if the player is covering a lot of distance (and no enemies are present), and pans to the centre of the action when a dogfight is in place. I think it works pretty well.

I’m particularly pleased with the way the camera snaps to the closest enemy. I don’t know if it’s still too motion-sickness-inducing (maybe) but it feels much more visceral, seems to help with gameplay, makes it easier to get combos, and, in certain situations, just makes the player feel like a complete badass! So I think I’m going to park the camera now and wait for user feedback before I go tweaking it further…

Dev Time: 2.5 days
Total Dev Time: approx 96 days

previous|next

mockup_3x
Camera Motion Based On Player Velocity

mockup_3x
Camera Motion Based On Duration Of Movement

mockup_3x
Camera Motion Based On Closest Enemy

mockup_3x
Camera Motion Based On All Of The Above #1

mockup_3x
Camera Motion Based On All Of The Above #2

Jetboard Joust Devlog #42 – Evil Mothers

Another new enemy in the bag – this one’s called the ‘mother’! At least that’s what I’m referring to it as now anyway.

As with the previous enemy it’s heavily inspired by one of the enemies from the original Defender, in this case the ‘pod’. The main ‘selling point’ of the pod is that when it’s destroyed it releases a bunch of smaller, faster enemies called ‘swarmers’ that use kamikaze tactics to attack the player.

The ‘mother’ works in pretty much the same way. As I’m going for a more ‘character’ based approach to most of my enemies I thought it would be nice to have the original enemy split in to smaller ‘mini me’ versions of itself when destroyed – a kind of mother/child thing.

For the design of the enemy I went for a kind of insectoid ‘space invader’ type approach. It’s consistent with the design of the ‘mutant’ enemy and also I knew I could get this to work at a very small size for the ‘children’. Strangely the hardest thing to get right here was the eyes which I wanted to look like a cross between real eyes and some kind of electronic ‘scanner’ – as though the eyes are on an LED screen or something with a lot of interference.

I’ve made the ‘mother’ probably a bit more dangerous in its original incarnation than the Defender ‘pod’. The AI tracks the player in ‘bursts’ similar to the ‘bomber’ enemy but not restricted to either purely horizontal or vertical movement. It uses a similar simple technique to avoid getting stuck in between buildings as well, ie when it collides with a building it will move upwards until above the level of the building. It also fires slow-moving bullets.

The ‘children’ were basically an extension of the ‘mother’ class with different motion parameters so, thankfully, it didn’t take long to get these up and running at all. I added particle effects to both, a kind of anti-gravity field or something. Note how these get disturbed when the enemy collides with a building or takes damage!

I spent quite a while tweaking the motion parameters of both mother and children, both to get them to feel right in relation to each other and also to get the children to feel like they were moving in a ‘swarm’ without working too obviously in unison. The actual ‘birth’ sequence to a while to get right as well, it needs to be slow enough to see what’s going on yet fast enough to feel like the children are being propelled out as speed. I also added some particles to the birth sequence to give is some more ‘pazazz’. Needs audio too..

Dev Time: 2 days
Total Dev Time: approx 58.5 days

previous | next

mockup_3x
Original Enemy Design – Mother & Children

mockup_3x
Adding Motion And Particles To The Mother

mockup_3x
The ‘Birth’ Sequence

Jetboard Joust Devlog #37 – Shake, Rattle & Roll!

I’d been thinking for a while that I needed a slightly more visceral feel to the collisions in Jetboard Joust, particularly when the main character crashes into the terrain but also when he’s taking damage from enemies.

So I’ve spent the last couple of days working on this by applying three different effects, the amount of each effect applied depends on the strength of impact (ie the speed the player is travelling or amount of damage taken) and is tweened back to zero over a short period of time, roughly 0.25 seconds. The three effects are as follows…

1. Scanner Distortion
It didn’t make sense to me that the scanner display should remain pristine when you’re taking a pummeling. Though the scanner is part of the HUD I imagine it as being embedded in the player’s helmet or something so it should appear to suffer as the player does whilst still maintaining enough legibility to make the game playable. I’ve achieved this by applying a ‘pixelator’ type shader that is based on my ‘teleport’ shader with a few changes. As well as changing the amount of pixelation based on the strength of impact I also add a small amount of brightness and noise which gives the impression of old-school CRT interference.

2. Camera Shake
This effect has become so much a staple of indie games that it’s almost a cliché by now but, what the hell – it looks good! Applying the effect was a bit more complex than I thought as it needs the appearance of randomness without being genuinely random (because a genuinely random shake can appear to stick at times). My final approach was to take a {1,0} vector, rotate pseudo-randomly, and then multiply the camera offset by the strength of impact on the x and y axis. For the pseudo-random rotation I always rotate by at least 90deg from the last ‘shake’ and then add another random amount between 0 and 180deg, this gives the appearance of randomness but always ensures there’s a ‘whole lot of shaking going on’. I also keep track of the ‘static’ camera position so that the ‘shaken’ position is always offset from the ‘static’ position and you don’t get a ‘brownian motion’ type effect with the camera movement which would upset the standard camera taking of the player.

3. Impact Shader
This was the effect that took the longest to get right. In my head I wanted an effect applied to the terrain that was kind of a cross between ‘double vision’ and the ‘vibration lines’ you might see on static illustrations to give the impression of movement. I also wanted the effect to look a bit glitchy.

First step was, whilst the effect was in progress, render the entire terrain to an offscreen image rather than rendering directly to screen. The shader could then be applied to the entire terrain rather than each individual component of it which would be both inefficient and cause visual issues.

I then started by applying a shader that simply rendered the whole terrain in a flat colour with some scaling distortion applied, the scaling varying according to strength of impact. I found I had to apply this shader three times in order to get the ‘double vision’ effect on the top, left and right of each building.

I then tried applying some raster lines to the effect and found this looked best if I applied horizontal raster lines when the shader was distorting vertically and vice versa. This gave a ‘vibration line’ effect around the buildings.

Next I tried randomizing the amount of scaling every x pixels – so there would be more distortion at certain, regular, points. This gave a ‘spiky’ effect to the shader that I thought looked pretty cool.

Lastly I varied the amount of scaling distortion on each axis based on the direction of the player’s travel and also added a certain amount of pixelation, again dependent on the direction of travel. I’m pretty pleased with the effect now though it has taken a hell of a lot of tweaking to get this far. No doubt I won’t be able to resist tweaking it some more either!

Dev Time: 1.5 days
Total Dev Time: approx 44 days

previous | next

mockup_3x
One Of The First Impact Shader Attempts


Something A Little More Subtle


Adding Raster Lines For A ‘Shake’ Effect


Adding Scaling Spikes


Final (No Chance!) Impact Shader, Scanner Distortion & Camera Shake

Optimising Memory Use In MonoGame

Don’t we all love the garbage collector in .net? It frees us from that irksome task of allocating and releasing memory ourselves and (virtually) eradicates memory leaks. Hooray for the garbage man!

Unfortunately there’s no such thing as a free lunch and all this ease of use comes with a performance penalty – and potentially quite a nasty one at that. Each time the garbage collector kicks in there’s a small CPU spike which can cause an inconsistent frame rate or the appearance of ‘juddering’ in your game.

The solution is to try and make sure as little garbage build up as possible and (if necessary) manually trigger collection at points in your game where there’s a natural pause, for example on losing a life or completing a level.

So, here’s a few tips on minimising the garbage… I welcome any feedback on any of these or any other suggestions.

1. Reuse and Recycle
Any game is bound to have a bunch of objects that are used and discarded on a regular basis. Sprites, rectangles, animations etc etc. Rather than creating and discarding these on an ‘as needed’ basis create a ‘pool’ of objects up front and retrieve and return them to the pool as required. This approach obviates the need for both memory allocation and garbage collection for the applicable objects in-game and can have a very positive impact on game performance.

Of course this approach comes with a development overhead, you are now (effectively) back to managing memory yourself and have to be very careful that you don’t attempt to re-use an object once it has been returned to the pool and re-initialized. These types of bugs can be very tricky to track down!

Below is the template I use for a simple generically-typed object pooling system consisting of an ObjectPool class and an IPoolable interface.

using System;
using System.Collections.Generic;

namespace com.bitbull.objectpool
{
	/*
	 * Any object that is to be pooled needs to implement this
	 * interface and support a parameterless constructor.
	 */
	public interface IPoolable
	{
		/*
		 Should reset all the object's properties to their default state.
		 */
		void Initialize();

		/*
		 Called when an object is returned to the pool. The implementation of 
		 this method doesn't need to do anything but it can be useful for certain
		 cleanup operations (possibly including releasing attached IPoolables).
		 */
		void Release();

		/*
		 Set by the pool and used as a 'sanity check' to check this object came from
		 the pool originally
		 */
		bool PoolIsValid
		{
			get;
			set;
		}

		/*
		 Used by the pool as a 'sanity check' to ensure objects aren't freed twice.
		 */
		bool PoolIsFree
		{
			get;
			set;
		}
	}
	/*
	  Template for a generically-typed object pool - pooled objects must
	  implement the IPoolable interface and support a parameterless constructor.

	  To create a new pool - ObjectPool pool = new ObjectPool(int initial_capacity)
	 */
	public class ObjectPool where T:IPoolable,new()
	{
		// I use a Stack data structure for storing the objects as it should be 
		// more efficient than List and we don't have to worry about indexing 
		private Stack stack;
		// The total capacity of the pool - this I only really use this for debugging
		private int capacity;

		/*
		 Creates a new object pool with the specifed initial number of objects
		 */
		public ObjectPool( int capacity )
		{
			stack=new Stack( capacity );

			for( int i=0; i<capacity; i++ )
			{
				AddNewObject();
			}
		}

		/*
		 Adds a new object to the pool - ideally this doesn't happen very often 
		 other than when the pool is constructed
		 */
		private void AddNewObject()
		{
			T obj=new T();
			obj.PoolIsValid=true;
			stack.Push( obj );
			capacity++;
		}

		/*
		 * Releases an object from the pool - note that there's no real need 
		 * to throw the first exception here as if an object is freed twice it's not
		 * really a problem, however the fact that this is happening usually indicates 
		 * an issue with one's memory management that could cause issues later so I 
		 * prefer to leave it in.
		 */
		public void Release( T obj )
		{
			if ( obj.PoolIsFree )
			{
				throw new Exception( "POOL ("+this+"): Object already released " + obj );
			}
			else if ( !obj.PoolIsValid )
			{
				throw new Exception( "POOL ("+this+") Object not valid " + obj );
			}
			obj.Release();
			obj.PoolIsFree=true;
			stack.Push( obj );
		}

		/*
		 * Retrieves an object from the pool - automatically create a new object if the pool
		 * has become depleted.
		 * 
		 * Calls Initialize() on the released object which should set all its parameters to
		 * their default values.
		 */
		public T Get()
		{
			if (stack.Count==0)
			{
				AddNewObject();
			}
			T obj=stack.Pop();
			obj.Initialize();
			obj.PoolIsFree=false;
			return obj;
		}
	}

}

2. Don’t Create Temporary Objects
Avoid the temptation to do stuff like this in your code (and I don’t mean the ridiculously long variable names)…

public void SomeMethod()
{
	FooBar some_temporary_object_needed_for_a_calculation = new FooBar();
	//
	// Do some stuff that needs a temporary FooBar object 
	//
	return;
}
Instead (providing your code is thread safe) make the FooBar object a ‘scratch’ class variable (so it persists for the life of the containing object) or even better a static variable (so that it persists for the lifespan of your app). Note that I don’t think there’s really any point in doing this with temporary structs as their creation/disposal is relatively trivial compared to that of classes.
private static FooBar foobar_scratch;

public void SomeMethod()
{
	//
	// Do some stuff with the 'scratch' FooBar object 
	//
	return;
}

3. Stack ‘Em Up
If you have objects that are not being pooled (because it’s too much effort or whatever) consider adding them to a Stack on creation and only emptying the stack at a point where there’s a natural pause in the game. Note that you have to watch your overall memory use with this approach as you have basically, albeit deliberately, created a massive memory leak! Only really suitable for small objects or those that aren’t created that regularly.

4. Avoid Using SetRenderTarget()
Even though it’s used in most examples SetRenderTarget() creates a bunch of garbage and should be avoided. Use SetRenderTargets() instead (even if you have only one). There’s more information on this (and some other cool tips) here.

5. Overload Your SpriteBatcher
When running some diagnostic tools on Jetboard Joust I realised that there was a bunch of wasted memory generated by the MonoGame SpriteBatch class. It seems that for every render an array is created to the size of the number of ‘draw’ operations to be executed. Whilst this array persists to an extent (much like the Collections classes a new array is only created if the old one doesn’t have enough capacity) when the amount of render operations can increase and vary considerably (for example with particle systems) you have, potentially, an awful lot of memory allocation and retrieval going on.

The solution I’ve tried for this (which appears to work) is simply to hammer your SpriteBatch with a load of render operations the first time around to ensure that an array is created that’s big enough to cover most scenarios.

6. Watch Those Strings
Though you wouldn’t think it, strings are a common cause of memory problems – particularly where there’s string concatenation involved (as there is in most debug calls). There appears to be an especially JNI-related nasty memory ‘leak’ (ie tons of garbage getting created) involving strings in the MonoGame Android implementation (though it’s deep in OpenTK rather than in the MonoGame code per se).

Be particularly wary of ‘debug’ type calls where your debug string may still be being created even if it’s not being output!

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

Animated GIFs of Gameplay Footage for Twitter on Mac OSX

I’ve been asked how I do this a few times on Twitter so thought I’d write a post about it. Haven’t done a ‘tutorial’ style post in a while. My bad.

Posting animated GIF images on Twitter is a very good way to get retweets and likes and build awareness of your game, but if you’re using a Mac there aren’t that many tools out there for the job. Most people seem to use GifCam on PC but there doesn’t seem to be a Mac equivalent.

In a nutshell I use Apple’s Quicktime Player to screen capture followed by a process in Photoshop to crop and convert to animated GIF. I tried a bunch of different tools and processes before deciding on this as by far the best way.

Make your GIFs 506 pixels wide by less than or equal to 506 pixels tall so that Twitter doesn’t resize them and make them all blurry (especially important for pixel art).

Photoshop has a stupid 500 frame limit for animated GIFs but you’ll probably hit Twitter’s 5mb size limit before this becomes a problem. It is, unfortunately, a problem sometimes though.

So, in detail…

1. Decide On An Emulator
I’m developing cross platform with Xamarin/MonoGame and have found by far the best emulator to use is GenyMotion for the Android platform. I use this for general development and for all screen capture. The iOS emulators are way to slow and grabbing video direct from iOS device is also too flakey and produces too many compression artefacts. The GenyMotion emulator is very fast and can be reliably run at 1:1 ration for pixel art – only downside is that the 1:1 function requires a ‘paid for’ licence.

Xamarin’s free Android Player is pretty good but at the time of writing there are bugs in the handling of key events which means I can’t use it for my purposes.

2. Capture
I use Apple’s Quicktime Player for this. I was using Snapz Pro but it only seems to capture up to 30fps. To screen capture from Quicktime Player just click ‘done’ on the first dialog that pops up then go to File->New Screen Recording. From there it’s self-explanatory.

3. Edit
This step is optional as you can do it in Photoshop. I find it much easier to crop the video to the section I want using Apple’s outdated but incredibly useful QuickTime Player 7 Pro. This is another paid app I’m afraid but it really makes the process a lot less painful.

4. Import Into Photoshop
Open your video in Photoshop and crop it to size. You can ‘scale up’ later when saving as a GIF so you could crop to 50% of your final size (or even less). This can look good for pixel art. Then I do the following procedure…

5. Adjust Colour Profile
– Edit->Assign Profile->Generic RGB Profile
Your mileage may vary on this but I find that screen captures from Quicktime always seem too dark when importing into Photoshop. This alleviates that issue to an extent.

6. Create Layers
Open the animation window (Window->Animation) and in the menu at the top rioght of the animation window select ‘Flatten Frames Into Layers’. This may take some time. Once this is done select the original movie layer (it will be the bottom layer in the layers palette) and delete it.

7. Create Frames
Back to the animation window menu now – this time select ‘Make Frames From Layers’.

8. Save As GIF
You are now ready to export your animation. For some reason I’ve found that Photoshop often does something weird with the first frame, like it’s assigned a different colour profile or something. You can check this by moving the timeline marker in the animation window and seeing if everything looks OK. If it doesn’t you can more the ‘start’ marker to just beyond the problem frame (you can also use these start/end markers to crop the timeline if you didn’t edit your video as described in step 3).

Use ‘Save For Web’ to export and you will have to mess around with the colour settings to get your animation under 5mb. Even if your image contains no transparency keep ‘transparency’ checked as without it file size jumps up dramatically (maybe photoshop uses this to only update areas of each frame that change). Note that you can scale up your image at this point – be sure to select ‘Nearest Neighbour’ scaling for pixel art.

I’ve found that the ‘loop’ setting keeps getting set back to ‘once’ when other parameters are changed so make this the last thing that you do. Changing colour options and the like can result in a lengthy ‘beachball of death’ depending on the size of your GIF so when you see this don’t panic just wait it out.

It’s easy to set up a Photoshop Action to cover steps 5 through 7.

That’s it. Any questions or comments please contact me here or on Twitter.

Implementing A Custom C# Generic Type Enumerator

I’ve just run up against something in ‘Jetboard Joust’ whereby I needed to implement a custom generically-typed enumerator that I could enumerate through using the foreach statement along the lines of…

FooBar enumerator;
foreach( Foo foo in enumerator )
{
	// do some stuff
}

Unfortunately I found Microsoft’s documentation on this to be vague to the point of being misleading, and most of the StackOverflow answers weren’t much use either.

So here’s a simple example that defines a custom generic-type enumerator (implementing the IEnumerable and IEnumerator interfaces) that can be iterated through using the foreach statement. I’ve commented on the things that I found slightly odd – the main one being the fact that MoveNext() is called before the first object has been retrieved.

I’m using Xamarin and possibly Mono operates slightly differently than ‘native’ .net but it shouldn’t do.

Hope this helps someone…

using System.Collections.Generic;
using System.Collections;

namespace com.bitbull
{
	public class FooEnumerator:IEnumerable,IEnumerator
	{
		#region properties
		private Foo[] foo=new Foo[24];
		private int count;
		#endregion

		public FooEnumerator()
		{
		}

		/*
		 * Called at the start of each foreach statement and it
		 * would appear this is the best place to initialize your 
		 * counter. Note that, unintuitively, I start on -1 rather
		 * than zero as MoveNext is called before the first object in
		 * the enumeration is retrieved
		 */
		public IEnumerator GetEnumerator()
		{
			count=-1;
			return this;
		}

		/*
		 * I'm not really sure why you need this here but 
		 * it won't compile without it
		 */
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		/*
		 * Called each iteration of foreach BEFORE the current
		 * object is retrieved. Unintuitively this means that if
		 * you start your count on zero you will miss the first
		 * object in your enumeration.
		 * 
		 * Should return true or false depending on whether there
		 * are further objects available to iterate through
		 */
		public bool MoveNext()
		{
			if (count>=foo.Length)
			{
				return false;		
			}
			else
			{
				count++;
				return (count<foo.Length);
			}
		}

		/*
		 * I am not entirely sure when this gets called but you 
		 * need to implement it! It doesn't seem to get called at
		 * the start of each foreach statement which is what I 
		 * presumed would happen. I reset the counter here anyway
		 * as it seems the sensible thing to do but this method
		 * never seems to get called in my code.
		 */
		public void Reset()
		{
			count=-1;
		}

		/*
		 * Returns the current object in the enumeration
		 * called on each iteration of foreach
		 */
		public Foo Current
		{
			get { return foo[count]; }
		}

		/*
		 * I'm not really sure why you need this here but 
		 * it won't compile without it
		 */
		object IEnumerator.Current
		{
			get{ return this.Current; }
		}

		/*
		 * You need to implement this as well, again I'm not
		 * really sure why this is really necessary.
		 */
		public void Dispose()
		{
		}
	}

	public class Foo
	{
		public Foo()
		{
		}
	}
}

Directional Control Systems for Touchscreen Games

A while ago I wrote a blog post entitled An iPad Is Not A GamePad describing my aversion to virtual ‘d-pad’ (I’ll call them ‘v-pad’) style controls for touchscreen games.

Well, whaddya know – a potential publisher for ‘Attack Of Giant Jumping Man’ has asked to see the game working with a ‘v-pad’ style control system as he’s worried the existing ‘swipe’ control system is not intuitive enough. Personally I just think we need to improve the way we communicate how the existing system works – but, as I’m never one to let my prejudices get in the way of improving the game experience, I decided to roll up my sleeves and see if I could get a decent ‘v-pad’ style control system going. It wasn’t easy and I’ve documented my experiments here. I’ll cover button placement in another post as this one got rather out of control!

First off, as I knew I was going to be experimenting with several different control methods, I had to completely separate the ‘controller’ logic from the ‘game’ logic. I guess this is something that’s pretty standard practice with other application designs (MVVM, MVC etc) but I never really think about doing it with games as (usually) you know what the control method is going to be from the outset and the game is designed with this in mind. Ultimately it makes more sense to keep the controller logic abstracted though (especially in today’s cross-platform world) and, now I’ve been through the pain, I will definitely be approaching game design this way in future. It allows a bunch of different control systems to be easily tested/switched without any alteration of the game code.

So I came up with a generic ‘controller’ interface that produces the usual ButtonPressed / ButtonReleased type events as well as allowing polling to see whether a particular button is held down and the position of two ‘virtual analog thumbsticks’ which produce values between -1.0 and 1.0 on both the horizontal and vertical axis. Basically pretty much an abstracted representation of the XBox Controller.

Next stage was to experiment with some different controllers, I’ll go through each of these in turn…

The Virtual D-Pad
This is the simplest approach of the lot. Basically a virtual button for up/down/left/right that produces a binary KeyHeld result if the user is pressing the screen in the appropriate place.

This method is very easy to implement but, in my opinion, sucks for the following reasons (many of which apply to all v-pad style controllers).

1. It requires an overlay on the screen to show the user where to press. This uses up valuable screen real-estate and potentially gets in the way of the action.

2. It requires the same size controller whatever the physical size of the device, therefore is much more problematic on small devices. A fact that’s blindingly obvious but a lot of developers ignore is that people’s thumbs are the same size whether they’re using an iPhone 4s or an iPad. Think how much research goes into designing the perfect d-pad size for a console controller, now imagine sticking one of those on top of a 4s screen – kind of get in the way of the action wouldn’t it?

3. It requires the user to hover their finger/thumb over the same area of the screen all the time. Again, using up valuable screen real-estate and potentially getting in the way of the action. As above, on a physically smaller device this is even more of an issue.

4. It’s too easy to stray off the controls. With a physical controller you can feel your thumbs resting on the controls without actually pressing them – it’s very unlikely you’ll slip onto the wrong control accidentally, let alone slip off the entire controller. Modern touchscreen devices however are designed to be as super-smooth as possible with no tactile differentiation between the screen itself and the ‘dead’ frame of the device. This makes it all to easy to stray into the ‘dead zone’ without realising it.

You could implement your own tactile feedback solution, ie vibrate the device when the user strays into the ‘dead zone’, but there are a number of issues with this. Firstly, not all devices support a vibrate function (iPads and tablets don’t tend to) and auditory feedback is likely to be annoying – secondly, in order to implement this you are reliant on getting a ‘TouchReleased’ event when the user strays into the ‘dead zone’ and for that event to be accurate enough to warrant doing something with. In my tests on an iPad 4, when moving quickly that event could be generated up to 45 pixels from the edge of the screen – that’s 0.25inch so probably within the bounds of a ‘normal’ release event.

As you can tell, I’m not a fan of this option and can’t really see any situation where it’s decent control method to use. This brings us on to…

The Virtual Thumbstick
This method is similar to the ‘Virtual D-Pad’ described above. However, instead of simply checking whether we have pressed a virtual button to determine directional control we measure the distance of TouchPressed and TouchReleased events from a central point and use this to compute a value between -1.0 and 1.0 on the horizontal and vertical axis. This can be converted to a binary event if necessary by testing against a threshold value. A TouchReleased event resets all values to zero.

The computation I use for calculating the x and y values is something like this…

//
// Calculates thumbstick values and y between -1.0 and 1.0 where px and py
// are the distance of the touch event from the centre of the virtual thumbstick
// and radius is the distance required to produce a maximum value
//
public static void CalculateThumbstickValues( out float x, out float y, int px, int py, int radius )
{
// Work out x and y distances as a proportion of radius
x /= radius;
y /= radius;

if ( x>1.0f ) x=1.0f;
else if ( x<-1.0f ) x=-1.0f;

if ( y>1.0f ) y=1.0f;
else if ( y<-1.0f ) y=-1.0f;
}

This method has certain advantages of the ‘Virtual D-Pad’ method. It’s not restricted to binary events and, importantly, it doesn’t require the user to target one area of the screen quite so much as any deviation from the ‘edge’ of the thumbstick area reads as a maximum value. Consequently I find it works much better.

It still suffers from the fact that it requires some kind of visual overlay (though technically only the very centre point of the thumbstick needs to be marked), that it’s restricted to one area of the screen (so better make sure it’s not getting in the way of anything important), and (worst of all) that a user can still easily stray into the ‘dead’ zone (effectively letting go of the thumbstick).

Given these problems I thought I’d work on a couple of variations of the ‘Virtual Thumbstick’…

The Floating Thumbstick
This method is identical to the ‘Virtual Thumbstick’ with the difference that the thumbstick isn’t fixed to a set centre point – instead the location of the stick changes every time a TouchPressed event is received.

The advantages of this method are twofold – no visual overlay is required and the user can direct their input to a location on the screen that doesn’t get in the way of the in-game action (possibly making it less likely that they will stray into the ‘dead zone’).

One disadvantage of this method is that the player has to make a small drag motion for each TouchPressed event in order to generate any kind of directional data. On some types of games this might become an issue.

Another disadvantage is that if the player generates their original TouchPressed event near to the edge of the screen (say at the left edge) it then becomes impossible to move left without first releasing touch.

Generally I found that this control method works very well as long as the game in question is designed for one-handed play. On games that require two-handed play players will tend to position their thumbs permanently over the same area of the screen anyway, pretty much negating any advantage this control method brings.

The Elastic Thumbstick
This method takes the idea of the ‘Floating Thumbstick’ one step further. As well as centering on TouchPressed the thumbstick also centres after a defined period of inactivity, though in this instance it continues to read its last ‘set’ value.

As an example – on a thumbstick with a radius of 50 pixels a swipe to the right of 50 pixels will generate a value on the x axis of +1. If the user doesn’t release and doesn’t move their finger the thumbstick will be re-centred but continues to read +1 on the x-axis until a significant movement in the other direction on the same axis is made.

The thumbstick is also recentered if the user makes a sudden change of direction, so a swipe to the right of 50 pixels on the same thumbstick followed immediately by a swipe to the left of 50 pixels will result in the thumbstick being recentered in the +50 position (now reading 100% left).

The advantage of this approach over the ‘Floating Thumbstick’ is that it takes a much less significant movement to change direction on either axis. Consequently the problem of centering the thumbstick at the edges of the screen is negated and the amount of screen real estate required to process movement (and therefore be blocked by your user’s fat thumbs) is reduced by approximately 50%.

The only real disadvantage is that this control method doesn’t allow for ‘decceleration’, ie setting a thumbstick to max and then reducing this value – however, in practice this won’t make a lot of difference on most games and no difference at all on games that are using the thumbstick as a ‘binary’ controller.

In practice I found this method to operate best on two-handed games or on one-handed games where no decceleration is required and quick changes of direction are key to gameplay. It’s more finicky to set up than the others but well worth the effort.

NOTE: I also tried a similar approach by polling average movement on the touchscreen every few frames but this was pretty much a disaster.

The Sticky Elastic Thumbstick
OK, the names are getting pretty ridiculous now and a ‘sticky elastic thumbstick’ sounds distinctly dodgy but who cares. This is a new one based on gameplay testing I’ve just been doing on Jetboard Joust. It operates exactly like the ‘elastic thumbstick’ above with the difference that a straightforward touch event with no movement generates the values the thumbstick was set at the last touch release rather than zeroing the thumbstick and waiting for another movement.

This has the effect of a drag motion being required to set the direction but no movement being required to continue to move in that direction which makes control a lot easier and makes it a hell of a lot less likely that the players thumbs stray onto the ‘dead zone’. It seems to work extremely well on Jetboard Joust.

The Event-Driven Thumbstick (Swipe Controls)
This method is based on the ‘Floating Thumbstick’ with the key difference that it does not support continuous polling of thumbstick values. Instead it is event-based – a thumbstick event begins on TouchPressed (when the thumbstick is centered) and ends in one of two ways…

1. A TouchReleased event is generated within a specified time (approx <750ms)
2. The thumbstick is 'moved' to it's maximum position on any axis (different thresholds can be set for different axis if necessary)

… either of these causes an event to be sent to the game which is then processed appropriately.

The real advantage of this control method is that (with certain games) it allows one-handed operation where two-handed operation would normally be necessary (for example LEFT, RIGHT and JUMP). This in turn means that the user is free to swipe anywhere on the screen and that their thumbs and fingers are far less likely to get in the way of the action. Using this method also means that there's no requirement for the user to 'hover over' or touch any particular point of the screen for any length of time, again meaning that less of the action is likely to be obscured by fat fingers.

The disadvantage of this method is that the game needs to be suited to event-driven rather than continuous polling-based control. A game that requires a character to run in certain directions for long periods of time for example would be annoying to control by endless swiping, though there may be workarounds for this (e.g. swipe to move, tap to stop moving).

In practice I find the event-driven method to be the best way of controlling touchscreen games providing the game design is suited to it and the game can be operated one-handed. The event-driven method can enable very accurate control, obscures the screen far less than other methods, and never really runs the risk of the user losing control by straying into the 'dead-zone'. It's still our preferred control method for 'Attack Of Giant Jumping Man'.

Out of the two-handed methods the ‘elastic thumbstick’ seems to be the best compromise in this instance. 'Attack Of Giant Jumping Man' requires the user to make quick directional changes and the ‘elastic thumbstick’ allows for this whilst obscuring a minimum of the screen real-estate.

mockup_3x
Seriously, Just Don’t!