Category Archives: Development

Using A Custom Icon Font in Xamarin.Forms

Anyone who has done much mobile development work knows the pain of managing multiple bitmaps for devices with different screen resolutions. It’s a particular bugbear for Android developers due to the plethora of different devices available and the fact that Google’s default method of choosing appropriate resources (screen density) is not always an accurate indicator of screen size.

It would be much better all round to use vector graphics instead, but as (at the time of writing) native support for SVGs on both iOS and Android is patchy at best it’s no surprise that there’s no vector graphics support in Xamarin.Forms.

Fortunately there’s a decent workaround for monochrome vector graphics – use a custom font instead. You can either use an existing icon font such as Google’s excellent Material Icons set or the ones from Font Awesome, or use a tool such as IcoMoon which enables you to create your own font from SVG files created in Illustrator or similar.

So here’s how you do it, for the purposes of this tutorial we’re going to be applying Google’s Material Icons font to the Xamarin.Forms.Label control but the same approach can be used for different fonts and controls (e.g. Xamarin.Forms.Button).

You can download a .zip file for the project here.

1. Create A Custom Control
Just so we don’t get confused we’re going to create our own subclass of Xamarin.Forms.Label called IconLabel. Add a new empty class file to your shared project like so…

using System;
using Xamarin.Forms;

namespace CustomFontDemo
{
	public class IconLabel:Label
	{
		public IconLabel ()
		{
		}
	}
}

This custom IconLabel will work exactly like a standard Xamarin.Forms.Label on the whole, but for the purposes of this tutorial I’m going to add an instance of it to the page that the default Xamarin.Forms app creates at startup. The resulting XAML looks like this..

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
			 xmlns:local="clr-namespace:CustomFontDemo" 
			 x:Class="CustomFontDemo.CustomFontDemoPage">
	<local:IconLabel Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Nothing remarkable here, if you run the app at this point it should operate exactly like the default Xamarin.Forms app. Now we’re going to get the icon font to work which requires a bit of platform-specific tinkering

2. Import Your Custom Font Into Your iOS Project
Right-click on the Resources directory in your iOS project and select ‘Add Files’. Navigate to the font file you have chosen on your hard drive and add it to the project. Once the file has been added right-click on it and check the ‘Build Action’ is set to ‘BundleResource’.

mockup_3x
Where To Import The Font File On iOS

Now select your ‘info.plist’ file and click the ‘Source’ tab. Right-click anywhere in the editor and select ‘New Key’. You need to change the name of the key from ‘Custom Property’ to ‘UiAppFonts’ and then add an entry where it says ‘String’ for the file name of your font. In this instance ‘materialicons.ttf’.

mockup_3x
Info.plist Settings On iOS

3. Write A Custom Renderer For iOS
Custom renderers are used when you want to override the default behaviour for a particular UI component on a particular platform. In this case we are overriding the default renderer for our IconLabel class to use the font we have just imported.

Add an empty class file to your iOS project and edit like so…

using System;
using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

// This informs the compiler that we're using this class to render an IconLabel on this platform
[assembly: ExportRenderer (typeof (CustomFontDemo.IconLabel), typeof (CustomFontDemo.iOS.IconLabelRenderer))]

namespace CustomFontDemo.iOS
{
	public class IconLabelRenderer : LabelRenderer
	{
		public IconLabelRenderer ()
		{
		}

		// sets the font for the platform-specific ui component to be our custom font
		protected override void OnElementChanged (ElementChangedEventArgs e)
		{
			base.OnElementChanged (e);

			double? fs = e.NewElement?.FontSize;
			// Note we're using the font family name here, NOT the filename
			UIFont font = UIFont.FromName ("Material Icons", (int)fs);
			Control.Font = font;
		}

		// Without this strange things happen if you update the text after the label is first displayed
		protected override void OnElementPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			base.OnElementPropertyChanged (sender, e);
			if (e.PropertyName.Equals ("Text"))
			{
				Label label = sender as Label;
				// Note we're using the font family name here, NOT the filename
				UIFont font = UIFont.FromName ("Material Icons", (int)label.FontSize);
				Control.Font = font;
			}
		}
	}
}

4. Set The Text To The Appropriate Icon
Any custom icon font should come with documentation showing which icon maps to which unicode text character. Usually this is done with HTML-encoded values. For the purposes of this demo I’m going to use the value for the ‘favourites’ icon in Google’s Material Icons font. I can reference this directly in the XAML like so, note I’ve alse increased the font size for the label here too!

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
			 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
			 xmlns:local="clr-namespace:CustomFontDemo" 
			 x:Class="CustomFontDemo.CustomFontDemoPage">
	<local:IconLabel Text="&#xE87D;" VerticalOptions="Center" HorizontalOptions="Center" FontSize="144"/>
</ContentPage>

Alternatively you can set the text in code using the WebUtility.HtmlDecode() method in the System.Net namespace.

Text = System.Net.WebUtility.HtmlDecode ("&#xE87D;");

Running the above code should give you a label displaying an icon from your custom icon font in iOS. To get things running in Android we have a similar (though slightly different) procedure.

5. Import Your Custom Font Into Your Android Project
Right-click on the Assets directory in your Android project and select ‘Add Files’. Navigate to the font file you have chosen on your hard drive and add it to the project. Once the file has been added right-click on it and check the ‘Build Action’ is set to ‘AndroidAsset’.

mockup_3x
Where To Import The Font File On Android

6. Write A Custom Renderer For Android
Add an empty class file to your Android project and edit like so…

using System;
using Android.Graphics;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

// This informs the compiler that we're using this class to render an IconLabel on this platform
[assembly: ExportRenderer (typeof (CustomFontDemo.IconLabel), typeof (CustomFontDemo.Droid.IconLabelRenderer))]

namespace CustomFontDemo.Droid
{
	public class IconLabelRenderer : LabelRenderer
	{
		public IconLabelRenderer ()
		{
		}

		// sets the font for the platform-specific ui component to be our custom font
		protected override void OnElementChanged (ElementChangedEventArgs e)
		{
			base.OnElementChanged (e);
			// Note we're using the filename here, NOT the font family name
			var font = Typeface.CreateFromAsset (Forms.Context.ApplicationContext.Assets, "materialicons.ttf");
			Control.Typeface = font;
		}
	}
}

And that should be job done – you now have scaleable vector-based icons using a custom font running on both iOS and Android in Xamarin.Forms!

You can download a .zip file for the project here.

mockup_3x
Custom Icon Font Running On Xamarin.Forms iOS

mockup_3x
Custom Icon Font Running On Xamarin.Forms Android

How To Use Google Maps In Xamarin.Forms

Recently I’ve been putting together an app development proposal for a potential client. It’s the sort of app that I think would suit Xamarin.Forms very well, only it has a large mapping component for which the client wants to use Google Maps on both Android and iOS.

At the time of writing the ‘built in’ Xamarin.Forms Map view has limited functionality and defaults to using Apple Maps on iOS. This makes it unsuitable for this project which meant I had to find and (roughly) test out an alternative before I could put a proposal together with any degree of confidence.

I managed to get it working in the end, but not without hitting all sorts of snags which I’ll document here in the hope it might make the process easier for someone else. Most of this information is scattered about the web but it’s difficult to find it all in one place.

1. Find A Suitable Library
Fortunately there’s a third-party open source Google Maps API in development for Xamarin forms which you can access here. Xamarin.Forms.GoogleMaps seems to be pretty full-featured so, rather than trying to reinvent the wheel, this is what I decided to use. Thanks very much to GitHub user amay077 for making this available.

2. Get It To Compile
Once downloaded from GitHub the next step is to get the Xamarin.Forms.GoogleMaps sample project to compile. This was pretty straightforward apart from a few error messages – you may run into the following on iOS:

This version of Xamarin.iOS requires the iOS 10.2 SDK (shipped with Xcode 8.2) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker. (MT0091) (XFGoogleMapSample.iOS)

To get round this either upgrade Xcode (groan) or do what I did and go to Project Options->Build->iOS Build and set linker behaviour to ‘Link Framework SDKs only’ which should fix it (you may have to clean and rebuild).

On Android you may get something like the following:

Could not find android.jar for API Level 23. This means the Android SDK platform for API Level 23 is not installed. Either install it in the Android SDK Manager (Tools > Open Android SDK Manager…), or change your Xamarin.Android project to target an API version that is installed.

A rare helpful error message this – to fix either do as the message says and go to Tools->SDK Manager and install the appropriate level SDK or go to Project Options->Build->General and select an SDK that you do have installed (I set it to Android 5.0 and it worked fine).

3. Install Google Maps On A GenyMotion Device
OK – I’m going to assume that a) you want to use an emulator for development and b) you are using GenyMotion as it’s by far the fastest. If you try and run the Xamarin.Forms.GoogleMaps sample project as is you will probably see a grey square where the map should be with ‘Xamarin.Forms.GoogleMaps’ in black text. This is because Google Play Services (which includes Google Maps) is not installed on GenyMotion by default. To do this I followed the instructions here (scroll down the page to where it says ‘Setup Google Play Services’). I was using an Android 5.0 GenyMotion device and did not need to do the first step (ARM Translation Installer).

Once you have flashed your virtual device you will get all sorts of irritating popup messages saying ‘Google Play Services Has Stopped’ and the like but if you just soldier on through this and update google play services and google maps via Google Play you should be OK. If you can get the standard Google Maps app running on the device you are sorted.

4. Create An Android API Key
So, assuming you have Google Maps running OK on your GenyMotion emulator, if you now try and run the Xamarin.Forms.GoogleMaps sample project you will just get what looks like a blank map (or a ‘barren featureless desert’ for Black Adder fans). This is because you haven’t supplied a valid API key – if you look through the Application Output of the app in Xamarin Studio you will see something like the following:

Authorization failure. Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.
In the Google Developer Console (https://console.developers.google.com)
Ensure that the “Google Maps Android API v2” is enabled.
Ensure that the following Android Key exists:
API Key: your_google_maps_android_api_v2_api_key
Android Application (;): FF:4B:77:38:AB:3A:F3:A8:42:CC:03:27:74:AA:CB:5F:66:A1:5F:D0;net.amay077.xfgooglemapsample

Copy the long hex string (SHA-1 certificate) and package name from this error message as this will save you faffing around with keystore commands later.

Now go to your Google Developer Console. On your Dashboard click ‘Enable API’ and select the Google Maps Android SDK. Now go to ‘Credentials’, click on ‘Create Credentials’ and select ‘API Key’ followed by ‘Restrict Key’.

You should now get a list of restriction options. Select ‘Android apps’ and enter the package name and SHA-1 certificate from the error message I told you to note down earlier. The API key can now be saved.

Note that you will have to enable access for both the ‘Debug’ and ‘Release’ versions of your app as they are signed differently and therefore have a different SHA-1 certificate. Simply run the app in both configurations and grab the application output as above to get the appropriate SHA-1 key for each.

Whilst you’re at it you may want to create an iOS API key (see step 5). It takes a few minutes for these to take effect so, once done, I suggest you go and make yourself a well-earned cup of coffee.

Now you need to embed your API key in your app. The way I suggest doing this is consistent with all the documentation on the matter – go to your AndroidManifest file and enter the following inside the tag:

<meta-data android:name=”com.google.android.geo.API_KEY” android:value=”YOUR_API_KEY” />
<meta-data android:name=”com.google.android.gms.version” android:value=”@integer/google_play_services_version” />

Replace ‘YOUR_API_KEY’ with your actual API key of course. Now your manifest file should look something like this:

<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221; android:versionCode=”1″ android:versionName=”1.0″ package=”net.amay077.xfgooglemapsample”>
<uses-sdk android:minSdkVersion=”15″ />
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />
<uses-permission android:name=”android.permission.ACCESS_LOCATION_EXTRA_COMMANDS” />
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />
<uses-permission android:name=”android.permission.ACCESS_CHECKIN_PROPERTIES” />
<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />
<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />
<uses-permission android:name=”android.permission.ACCESS_MOCK_LOCATION” />
<uses-permission android:name=”android.permission.INTERNET” />
<application android:label=”OpenHouse”>
<meta-data android:name=”com.google.android.geo.API_KEY” android:value=”AIzaSyDJ7qxHOOh_4A1PodKyU0MlkhFIsyZsNJ7″ />
<meta-data android:name=”com.google.android.gms.version” android:value=”@integer/google_play_services_version” />
</application>
</manifest>

Just one more step – in the Xamarin.Forms.GoogleMaps sample project the API key isn’t entered in this way so you will need to delete the ‘dummy’ API key that been placed there. Do do this simply open MyApp.cs and remove the following line:

[MetaData(“com.google.android.maps.v2.API_KEY”,
Value = Variables.GOOGLE_MAPS_ANDROID_API_KEY)]

Hopefully if you now rebuild and run the Android project, and you’ve waited long enough for your API key to activate, you should now be able to see Google Maps correctly displayed in the GenyMotion emulator. Well done – it’s not the simplest process in the world!

5. Create An iOs API Key
This is pretty much the same process as creating your Android API key. Go to your Google Developer Console. On your Dashboard click ‘Enable API’ and this time select the Google Maps iOS SDK. Again go to ‘Credentials’, click on ‘Create Credentials’ and select ‘API Key’ followed by ‘Restrict Key’. This time choose iOS app restriction and enter the bundle identifier from your Info.plist file. For the Xamarin.Forms.GoogleMaps sample project it’s ‘net.amay077.xfgooglemapsample’.

To embed the API key into your iOS application open AppDelegate.cs and pass the API key as a string in the call to Xamarin.FormsGoogleMaps.Init(). This should be all you need to get the app running on iOS.

6. Embed The Xamarin.Forms.GoogleMaps API In Your Own Projects
Assuming you’ve managed to run the sample project successfully it should be fairly simple to get the API working in your own Xamarin.Forms projects. Xamarin.Forms.GoogleMaps is in NuGet so, in a new Xamarin.Forms solution, right-clicking on the ‘packages’ folder and selecting ‘Add Package’ will allow you to add references to the Xamarin.Forms.GoogleMaps packages. Remember to add them to every project in your solution. You may need to enable ‘show pre-release packages’ in the NuGet browser in order to download versions that are consistent with the sample projects.

If you run into strange issues, such as XAML errors when setting properties on a Xamarin.Forms.GoogleMaps.Map view or ‘Could Not Resolve Type’ and ‘BadImageFormatException’ errors when trying to position the map then you most likely have an incompatible version of the various packages somewhere. Check that all your package references (both to Xamarin.Forms and Xamarin.Forms.GoogleMaps) are consistent in all of your projects and ideally the same as the sample project.

I hope this article saves you some of the pain and grief I endured whilst trying to get all the stuff to work. If it does I always appreciate more followers on Twitter here!

mockup_3x
FAIL – Google Maps Not Installed On GenyMotion Emulator

mockup_3x
FAIL – No Valid Google Maps API Key

mockup_3x
SUCCESS – Xamarin.Forms.GoogleMaps Working on GenyMotion Emulator

Jetboard Joust Devlog #54 – Smoke & Mirrors

For the past few days I’ve been working on adding some more ‘juice’ to Jetboard Joust – the sort of small details that don’t really add anything to gameplay per se but, when combined, add an awful lot to game feel (hopefully).

I’ll go over most of these in a separate post but one element seemed to deserve a post of it’s own – smoke.

I wanted to add smoke as a way of increasing a sense of ‘permanence’ to the combat. Explosions are over and done in less than a second but smoke could hang around for ten seconds or so and build up depending on how much destruction is going on.

I wasn’t after a ‘realistic’ smoke effect but something more stylised to fit in with the rest of the game art. It seemed logical to use circles as the base for the effect but I felt pretty sure I’d want these circles to increase in size over time, maybe quite dramatically, so I didn’t want to rely on scaling sprites for this. I decided to use custom shaders instead as this should give me much more control.

So the first step was to use a custom shader to draw a simple filled circle. Initially I thought the geometry behind this would be quite complex but, in fact, it’s just simple pythagoras. Here’s the approach in pseudo code…

// get coordinates relative to centre of circle
float x = 0.5-coords.x;
float y = 0.5-coords.y;

// fill the entire space
float radius = 0.5;

if ( x*x + y*y <= radius*radius )
{
// return a color
}
else
{
// discard
}

…I’d be lying if I said I got to this stage quickly though! Though it didn’t take me long to figure out the maths, I spent far too long passing the shader a region of a texture to draw rather than the entire texture and getting confused as to why my results were all off (forgetting that coords.x and coords.y are relative to the entire texture to be drawn, not the region). When I started passing a simple 2×2 image to the texture everything clicked into place.

Once I’d successfully drawn a filled circle it was pretty easy to expand that technique to draw concentric rings and the like, and to animate these by basing their radii on parameters that are passed to the shader and change each frame.

Next step was to find a way of applying motion to these circles that looked suitably smoke-like. I started by simple applying a uniform velocity to several circles distributed across a certain range, e.g. -60d to +60d, as well as increasing the circles size over time.

When I finally got this to work the way I intended it didn’t look too bad as a starting point so I added a couple more parameters to make things more interesting – a ‘deceleration’ parameter (so that the velocity of the circles decayed over time), and a ‘buoyancy’ parameter (so that the circles gradually floated upwards over time). I also decreased the opacity of the circles over time so that they gradually faded out.

This looked much better but the results were still far too uniform, forming very obvious geometric patterns as the circles intersected. To stop this I added a certain amount of randomisation to both the circles initial velocity and their ‘buoyancy’ – this produced a much more smoke-like effect – still stylised but not overly ‘geometric’.

I was almost there now but felt that the smoke cloud was dissipating too quickly and lacked some kind of ‘weight’ to it’s centre. I fixed this by adding additional batches of circles with a decreasing initial spread and velocity with the final one staying pretty much in the same place. This looked a lot better.

Lastly I experimented with adding pixelation to the shader so that the circles were drawn at the ‘game’ pixel resolution rather than the ‘screen’ pixel resolution. Unfortunately I felt this looked pretty crappy – one of those things that ‘should’ have worked but didn’t! So I left things as they were but I did add a gradually increasing amount of pixelation over time so that when the circles have pretty much faded out they kind of ‘dissolve’ out rather than just disappearing.

Actually I couldn’t stop there – I thought the centre of the smoke cloud looked too ‘solid’ to start with so added a small particle effect to imitate ash or something. It’s subtle but it just breaks things up a little.

I’m pretty happy with the final result – watch this space for a mini-tutorial on using shaders to draw geometric shapes. I think I might end up using that technique again in this game…

Dev Time: 1.5 days
Total Dev Time: approx 97.5 days

previous | next

mockup_3x
Successfully Drawing Circles With HLSL

mockup_3x
First Attempt At Multiple Circles – An Interesting Fail!

mockup_3x
Starting To Look More Smoke-Like But Still Too Geometric

mockup_3x
Adding Some Randomisation For A More Natural Effect

mockup_3x
The Final Shader With Pixel Dissolve

mockup_3x
The Final Smoke Effect In Game

Lerp Camera Motion Smoothing Tutorial and Example Code

Recently I’ve been revisiting at the way the camera works in Jetboard Joust – something that has been a continual thorn in my side throughout the project.

When researching how to make the camera movement better I came across many references to Lerp smoothing but I found few, if any, detailed explanations as to how this works in practice and (particularly) ways to get around its significant limitations. Cue this post, by the end of which we’ll have a class that’ll move an object smoothly towards a target point and ‘brake’ so it reaches it exactly no matter how often and by how much the target is changed.

I’m just concentrating on one axis of movement here for simplicity but this approach can easily be applied to 2D or 3D vectors. For those of you with short attention spans you can just download the final class here.

So… Lerp is a quasi-acronym for ‘linear interpolation’ and used to create smooth movement between two points. It’s often used to smooth out camera movement but can equally be applied to sprites or anything else in 2D or 3D space. The basic equation for Lerp is very simple, it takes a position and target, works out the difference between them and then returns a value a specified amount along that path. Only values >0 and <1 are generally meaningful.

public static float Lerp(float position, float target, float amount)
{
     float d = (value2 - value1) * amount;
     return value1 + d;
}

If you are using this equation to move an object and each frame call it with the object’s current position (keeping the other values the same) the object will move a smaller distance each frame which results in a ‘slowing down’ effect as the objects reaches its target. Here’s an example of this type of motion applied to a sprite. In this case the sprite is moving approx 480 pixels at a frame rate of 60fps with a Lerp value of 0.025.


Basic Lerp Smoothing

Now this looks pretty good already but, as you’ve probably figured out, there are issues. The first one is that using this approach the object will never actually reach its destination – this can result in a slightly jerky looking motion as it reaches the end of its trajectory as well as presenting potential issues if you want to do something when the destination is reached.

One way of resolving this is to implement a minimum amount of movement per frame. This can be anything you want but for many applications it makes sense for this to be one pixel.

Here’s a simple ‘Lerper’ class that implements this – each frame the amount of movement (LerpVelocity) is calculated and, if the absolute value of this is less the minimum velocity we clamp it at the minimum velocity. Of course this means that the object might now be in danger of moving beyond its target point so we check for this at well and make sure it doesn’t.

public static float Lerp(float position, float target, float amount)
public class Lerper
{
    public Lerper()
    {
        Amount = 0.025f;
    }

    // Returns the amount of movement at this stage of the lerp
    private float LerpVelocity(float position, float target)
    {
        return (target - position) * Amount;
    }

    public float Lerp(float position, float target)
    {
        float v = LerpVelocity(position, target);

	// If this is less than the minimum velocity then
        // clamp at minimum velocity
        if ( Math.Abs(v) 0) ? MinVelocity : 0 - MinVelocity;
        }

	position += v;
	// Now account for potential overshoot and clamp to target if necessary
        if ( (v= target))
        {
            position = target;
        }
        return position;
    }

    public float Amount
    {
        get;
        set;
    }

    public float MinVelocity
    {
	get;
	set;
    }
}

Here’s an example of this in action. As you can see it looks much better…


Lerp With Minimum Velocity Applied

Still we have limitations though if we’re looking for really smooth movement. The next glaringly obvious one is that Lerp is ‘ease out’ only, the object will be moving fastest at the start of the sequence which makes it look like it’s being fired from a slingshot rather than smoothly accelerating from rest.

To resolve this I’m going to apply an ‘Acceleration’ property to my Lerper class. This ensures that, if the object is increasing in speed, the increase doesn’t exceed a specified amount. This requires a variable to store the amount of movement each frame.

public class Lerper
{
    private float previous_velocity;

    public Lerper()
    {
        Amount = 0.025f;
        Acceleration = float.MaxValue;
    }

    // Returns the amount of movement at this staget of the lerp
    private float LerpVelocity(float position, float target)
    {
        return (target - position) * Amount;
    }

    // Returns the next position with lerp smoothing
    public float Lerp(float position, float target)
    {
        // get the amount to move
        float v = LerpVelocity(position, target);
        // don't allow increases in velocity beyond the specifed acceleration
        if ( v>0 && previous_velocity>=0 && v-previous_velocity>Acceleration )
        {
            v = previous_velocity + Acceleration;
        }
        else if (v < 0 && previous_velocity  Acceleration)
        {
            v = previous_velocity - Acceleration;
        }
        // If this is less than the minimum velocity then
        // clamp at minimum velocity
        if ( Math.Abs(v) 0) ? MinVelocity : 0 - MinVelocity;
        }
        // Remember the previous velocity
        previous_velocity = v;

        // Adjust the position based on the new velocity
        position += v;
        // Now account for potential overshoot
        if ( (v= target))
        {
            position = target;
        }
        return position;
    }

    public float Amount
    {
        get;
        set;
    }

    public float MinVelocity
    {
        get;
        set;
    }

    public float Acceleration
    {
        get;
        set;
    }
}

Here’s an example of this in action – now we have a nice ‘ease in’ to our Lerp motion. Here I’m using an acceleration value of 0.25f.


Lerp With Maximum Acceleration ‘Ease In’ Applied

There’s one other problem I’m going to address though. This ‘ease in’ effect works nicely if the object is initially at rest or moving in the same direction but if the object had previously been moving in the opposite direction we’re still going to get a nasty jolt. Here’s an example where I’m changing the destination to the opposite side before the previous Lerp has reached the end of its trajectory.


Sudden Changes In Direction Result in A Nasty Jolt

So we’re going to check for this in the code and again apply a maximum amount by which the velocity can change each frame. Remember that because we’re changing direction the absolute value of the current velocity at the point of change is the sum of the absolute value of both the current and previous velocities, ie a change in direction from 10 to -10 would result in a new velocity of -20.

A side-effect of this is that the object will probably end up moving away from the target until it’s gathered enough momentum to change direction. As the code that clamps to the target position assumes we are moving towards the target we have to max out the target value if this happens.

We also have a special case check for our minimum velocity here as we need to make sure that if the minimum velocity is applied its applied in the direction that moves towards the target (otherwise the object could get stuck moving in the wrong direction).

public class Lerper
{
    private float previous_velocity;

    public Lerper()
    {
        Amount = 0.025f;
        Acceleration = float.MaxValue;
        MinVelocity = 0;
    }

    // Returns the amount of movement at this staget of the lerp
    private float LerpVelocity(float position, float target)
    {
        return (target - position) * Amount;
    }

    // Returns the next position with lerp smoothing
    public float Lerp(float position, float target)
    {
        // get the amount to move
        float v = LerpVelocity(position, target);
        // don't allow increases in velocity beyond the specifed acceleration (ease in)
        if ( v>0 && previous_velocity>=0 && v-previous_velocity>Acceleration )
        {
            v = previous_velocity + Acceleration;
        }
        else if  (v  Acceleration )
        {
            v = previous_velocity - Acceleration;
            // we might actually end up moving away from the target
            // here in which case we adjust the target so we don't get
            // clamped to it later
            if (v  0 && previous_velocity  Acceleration )
        {
            v = previous_velocity + Acceleration;
            // we might actually end up moving away from the target
            // here in which case we adjust the target so we don't get
            // clamped to it later
            if (v > 0-MinVelocity)
                v = MinVelocity;
            else
                target = float.MinValue;
        }

        // If this is less than the minimum velocity then
        // clamp at minimum velocity
        if ( Math.Abs(v) 0) ? MinVelocity : 0 - MinVelocity;
        }
        // Remember the previous velocity
        previous_velocity = v;

        // Adjust the position based on the new velocity
        position += v;
        // Now account for potential overshoot and clamp to target if necessary
        if ( (v= target))
        {
            position = target;
        }
        return position;
    }

    public virtual void OnTarget(){}

    public float Amount
    {
        get;
        set;
    }

    public float MinVelocity
    {
        get;
        set;
    }

    public float Acceleration
    {
        get;
        set;
    }
}

Here’s what happens when you suddenly change the Lerp target with this code applied – as you can see we now have a nice smooth movement no matter how often we change the target value.


Lerp With Maximum Acceleration ‘Ease In’ Applied

And that’s pretty much it. You can download the final class file here – in the final version I’ve also added a MaxVelocity property, a delegate to be called when the object reaches its destination, and tidied up the code so its not quite so verbose.

If you are in the process of coding a camera for a 2D game I highly recommend you check out this excellent article.

If you are looking for something to move smoothly between two points over a specified number of frames then you’re probably better off using some kind of tweening rather than Lerp. Check out Robert Penner’s excellent tweening/easing functions or the ‘smoothstep’ algorithm approaches described here.

Hopefully this article is of use – if so please consider following me on Twitter.

Jetboard Joust Devlog #51 – Under Instructions

This has been another one of those tasks I’d been putting off for a long time. The main app framework, options menu, instructions, etc etc.

I already had a set of classes that handled all this stuff, including a menu, instructions, highscores, about pages and a bunch of other functionality but it was incredibly bloated and old. In fact, looking back at the original file I see I created the first version in 2003 so that’s 13 years ago! It’s been ported from JavaME and had all sorts of cruft in there to deal with the idiosyncrasies of ancient mobile phones plus maintaining backwards compatibility with titles that will (thankfully) never see the light of day again. It’s served me well but it was time to start again (more or less) from scratch – even though I knew that was to be a fairly painful process.

So I kept some classes that were written comparatively recently and were relatively bloat-free (the actual menu itself and the highscore management stuff) and got rid of everything else, adding the necessary code back in a piece at a time, refactoring it, and going through every line to trim all the bloat. It took me over a day just to get the thing to compile!

A part of the process I also streamlined all the graphics scaling to work with pixel-art games (where everything is drawn from one set of graphics rather than loading in a separate set for different screen-sizes) and improved some of the visual UI feedback, animations and tweening. There may be a bit too much ‘bounce’ in some of the tweens, I’m using an ‘exponentially decaying parabolic bounce’ tweening algorithm that is all over the web but I can’t find anything to specify the ‘amount’ of the bounce and the maths is a bit over my head. I will try and get my head around it at a later date.

And now I have a streamlined, bloat-free ‘main app’ class that manages the main menu, highscores and instructions. There is still some functionality I need to add (and some that has moved to new classes) but I have ditched almost 4000 lines of confusing and redundant code which is a good feeling.

One aspect that I spent a fair bit of time on was the formatting of the instructions pages. I wanted a system that would be very easy to edit, reuse, and apply to other elements of the app (such as about screens etc) so created generic InAppDoc and InAppDocViewer classes. An InAppDoc is created from an XML document which defines various elements such as pages and paragraphs of text but can also have custom elements that can be rendered by a specific game (such as individual sprites or sprite groups). It should be straightforward to extend this system to cope with localisations or even to add custom tags for more complex page layouts etc. An example of the XML used to create the series of test pages on the right is here. I need to fix those flashing arrows!

Dev Time: 7 days
Total Dev Time: approx 91.5 days

previous|next

mockup_3x
The Tweaked Main Menu With Added ‘Bounce’

mockup_3x
Some Placeholder Instructions Pages To Test The InAppDoc classes

Jetboard Joust Devlog #49 – Gun Control

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

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

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

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

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

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

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

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

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

previous | next


Whoops – Too Much Recoil On The Gatling Gun

mockup_3x
The Final Gatling Gun In Action

mockup_3x
The Magic Shotgun – Enemies Should Shield Each Other!

mockup_3x
Fixing The Magic Shotgun

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

mockup_3x
Bodyguards Doing What They’re Paid To Do

mockup_3x
Assassin Enemies Wielding Gatling Guns – Beware!

Jetboard Joust Devlog #48 –Game (Not) Over

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

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

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

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

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

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

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

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

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

Plus a myriad of other small improvements and bugfixes.

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

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

previous | next


Kill Enemies In Quick Succession For A Bonus Multiplier

mockup_3x
You’re Gonna Need An Extra Life Or Two…

mockup_3x
Must… Try… Harder… Next… Time…

mockup_3x
Your Jetsuit And Jetboard Are Now Fully Upgradeable

Jetboard Joust Devlog #47 –Having Difficulty With Difficulty

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

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

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

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

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

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

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

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

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

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

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

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

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

SortedDictionary<EnemyTypes, SortedDictionary<WeaponTypes, List>> dictionary;

..so first we have a collection of every valid EnemyType in the bucket, then for each EnemyType a collection of each valid WeaponType, and finally for each EnemyType/WeaponType combination a list of each valid character-level of enemy and weapon that fits that combination.

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

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

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

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

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

previous|next

mockup_3x
The Current State Of Play

Jetboard Joust Devlog #46 –You Can’t Take It With You

Yeah, I know, been a bit quiet round here. Had a bit of time off!

Been working on some more ‘polish’, implementing stuff I’d been putting off for a while and getting various aspects of the gameplay to work together. Here’s what’s been on my ‘to do’ list these past few days…

Add More Cash
I only had one denomination of coinage which clearly wasn’t going to be enough to cover all the cash rewards in the game, not without spawning a ludicrous amount of pickups anyway, so I’ve designed and added a few more. Now there’s five different types of coin 1, 5, 10, 50 and 100. I may have to add a 500 later on.

Bloodstains
One of my favourite mechanics in the ‘Souls’ games is the way that, when you die, you lose all your ‘souls’ (the game’s currency) and can only retrieve them by returning to the place you last died and touching your bloodstain. It can be incredibly annoying losing all the ‘cash’ you’ve earned but it really makes dying something to be avoided (unlike in many modern games where dying is practically meaningless) and adds an extra tension to the next life too. I’ve implemented a similar mechanic whereby you lose all your cash on death and have to return to your abandoned jetsuit in order to retrieve it.

Weapon Unlocks
I’ve now properly implemented the feature whereby picking up an enemy’s jetboard unlocks the weapon they were carrying for your own use. A weapon crate will automatically spawn when this happens giving the user a chance to pick up the weapon they have just unlocked.

Upgrade Equipment
I’ve properly implemented this as part of the gameplay cycle so you are given a chance to upgrade equipment at the end of each level. This took longer than it should! Also added the jetsuit itself as an upgradeable item.

Redo Jetboard Particle FX
I was never that happy with the vertical thrust effect on the jetboard so I’ve redone this giving it a more ‘anti-gravity’ quality. I’ve also tweaked and re-aligned the particle fx for the horizontal thrust.

That’s it. I am getting there, slowly. The next task is to revisit the ‘difficulty’ algorithms for level creation to make them take account of different weapon and enemy levels.

Dev Time: 4.5 days
Total Dev Time: approx 71.5 days

previous


New Denominations Of Coinage

mockup_3x
The Infamous ‘Bloodstain’ Mechanic


Capturing An Enemy’s Weapon


Picking Up An Unlocked Weapon

Jetboard Joust Devlog #45 – Upgrades Are Available

Ah, UI work! Truly the most enjoyable part of building a game. I love building user-interfaces, it’s so much more fun that all that irritating ‘gameplay’ stuff. How I wish I could churn out menus and buttons and fiddle with bitmap fonts all day!

Not.

Building a decent user-interface is often a fiddly and mind-numbing task, yet it’s an absolutely essential part of the overall gameplay experience so cannot be skimped on. Fortunately the only menu-driven part of Jetboard Joust is the ‘weapon upgrade’ stage so I don’t have too much to worry about, but I need to get it right nevertheless.

Seeing as I have just finished the first alternative weapon I decided to bite the bullet (no pun intended) and just get on with the weapon upgrade screens. As expected it was a fairly fiddly and time-consuming task.

So, first step – design the UI. This part wasn’t so bad, I knew what info I had to get across so just went for a layout that was as clear and straightforward as possible whilst retaining a degree of visual interest. I wanted to keep consistent with the game HUD as well so in that sense a large part of the ‘look and feel’ was already defined. It took a few hours to get something I was happy with.

Only problem was it became apparent that I needed a second, larger bitmap font in order to bring some variation to the design. I went for one in the style of the numbers in the HUD which seemed to work well but, as with all bitmap fonts, it took a lot of fiddling around to get it working correctly.

I also thought I needed larger icons for the upgradeable items so had to design an icon for the pistol and shotgun. At the moment I’ve set this at 32*32 though am wondering whether I might need to accommodate different sizes.

Next step – build the design in code. I decided to do all the drawing in code so that it would be easy to expand the text boxes etc if I needed to rejig the design. Again, a pretty tedious and time-consuming process. It paid off though as there were a couple of instances where I needed to change things in the layout (due to underestimating the space I’d need for text) and this was simply a matter of changing the value of a couple of variables rather than redrawing everything in photoshop. The UI is drawn in three separate layers, the background ‘connectors’, the boxes and lastly the text and icons.

I then needed to get the text read ‘live’ from actual data. As it may not just be weapons that are upgraded I defined an IUpgradeable interface that specifies
the functionality an object must implement to be ‘upgradeable’. Maximum and minimum values are set for the various stats and upgrade costs and the values for each ‘level’ calculated on the fly. Spent quite a while on this and implementing it in the two weapons I’ve design so far.

This all worked fine but I couldn’t help feeling that the UI just felt rather ‘dull’. I needed something to give it a bit more life so decided to try and implement a kind of ‘radio static’ type effect along the lines of the interference effect you get on the scanner when the player takes damage. The scanner interference shader was the obvious place to start and by using this, and an awful lot of tweaking, I was able to get an effect I was happy with. I didn’t end up changing the shader code at all, just messing with various parameters. Only the layer with the text and icons is drawn using this shader.

Last task – make it work! I’ve tried to make the process as clear as possible for the user and give visual feedback where necessary – I’ll also add auditory feedback at a later stage. You can see I’ve ‘greyed out’ the upgrade cost and button if the user doesn’t have enough cash and show a confirmation message if the user does purchase an upgrade. the process is fairly simple so hopefully I shouldn’t need much more than that but I’d be interested in any feedback…

Dev Time: 5 days (told you this was time-consuming)
Total Dev Time: approx 67 days

previous | next

mockup_3x
First Mockup Of The UI

mockup_3x
The New Bitmap Font

mockup_3x
New Weapon Icons

mockup_3x
The Final Working UI With ‘Interference’ Shader