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 #57 – Title Deeds

Another fairly quick entry today – I now have a title screen!

This didn’t take too long to put together once I’d designed the logo – most of the time was spent messing around with different motion types. I knew I wanted the logo to move, and each word to move separately, but it took a while to get something I was happy with.

My first attempt had each word moving parallel to the ‘slant’ of the logo but for some reason I found this a bit disturbing, like the words were scraping against each other or something. There was something almost sexual about it and not in a good way. yes, I know that probably makes me weird. maybe it’s too extreme but I found it the visual equivalent of hearing nails scrape down a blackboard (if any of you are young enough to remember blackboards).

My second attempt had each word moving in a less uniform elliptical motion. I preferred this so have stuck with it for now. I did also have to separate each word on the logo and also separate the actual letters from the background which took some pixel-pushing (there’s actually four sprites here).

Adding the parallax was easy as I could pretty much just use the classes that handle this in-game with a few minor tweaks. I’m pretty pleased with the end result and think it’s certainly presentable enough for the alpha version.

Dev Time: 0.5 days
Total Dev Time: approx 100.5 days

previous

mockup_3x
This Is The Motion That I found Weirdly Disturbing

mockup_3x
The Final (for now!) Title Screen

Jetboard Joust Devlog #56 – Pointing Out The Obvious

Whoa – 100 days of development under my belt!

Kind of a brief entry this one – I thought I was done with adding extra gameplay stuff for the alpha but watching my son play the game I realised there were a few things that were a little unclear.

The main one was the location of ammo stashes. It’s really annoying when you run out of ammo (I’m still not 100% sure that I shouldn’t give the base weapon unlimited ammo) and sometimes, in the heat of battle, it’s hard to locate the nearest ammo cache onscreen or on the scanner. This is even more of an issue since I added enemy bones which clutter up the battlefield.

So I’ve added two new features to make it easier to locate ammo, shields and rocket pickups – I call these ‘pickup detectors’ and ‘pickup indicators’.

A ‘pickup indicator’ simply indicates the location of the nearest onscreen stash – they don’t appear if the user’s ammo, rockets or shields are maxxed out. Implementing these was fairly straightforward, though I did have a few issues getting the indicator to move nicely between two different stashes. In the end I settled on having the indicator ‘pop out’ and then ‘pop in’ again when the location of the nearest stash changes. In my libraries I have a method that allows one to set a ‘timed event’ on a particular sprite, this is an event that doesn’t get triggered until a certain amount of frames later. This functionality has proved extremely useful for this type of thing.

A ‘pickup detector’ shows the closest route to the nearest stash if it is not onscreen. I settled on a simple arrow at the edges of the screen for this – not subtle but it works. As these would be annoying if they hung around all the time they only appear when the user’s shields or ammo are critically low. The rocket detector appears whenever a rocket pickup is present as these are pretty rare and you don’t want to miss them when they do appear.

The ‘pickup detector’ was also pretty straightforward to implement – the most fiddly bit was getting the arrows to centre correctly depending on how many of them there are, even that wasn’t that much hassle though.

I think these features make the game considerably more playable – plus I just love the look of that tiny pixel text!

Dev Time: 0.5 days
Total Dev Time: approx 100 days(!)

previous


Pickup Indicators In Action


Showing The Pop In / Pop Out As The Closest Stash Changes

mockup_3x
Please Sir – Where’s The Nearest Ammo Stash?

Jetboard Joust Devlog #55 – The Bubblewrap Effect

Everyone loves popping bubblewrap, yet no-one really knows why. For some reason the combination of the sound and tactile response makes it incredibly satisfying despite being utterly pointless. I had a friend who use to refer to this type of action as being ‘urgey’ – once you’ve done it you have the urge to do it again, and again, and again…

I’ve always thought we should aspire to this ‘bubblewrap effect’ when designing games. Most games, even the supposed AAA ones, comprise a fairly limited set of repetitive actions. If you can make those actions an enjoyable experience in and of themselves, regardless of gameplay, then you are onto a winner because no matter how good the player is at playing your game they will be having fun and come back for more.

Recently I’ve seen this loosely referred to as ‘juice’ or ‘game feel’ but these terms are rather vague and are often used to refer to all sorts of things. I’m talking about something pretty specific here – make all your repetitive actions as ‘urgey’ as popping bubblewrap. Usually this is a combination of both visuals and audio.

Now I’d already spent a lot of time on this stuff in Jetboard Joust but, whilst surfing GDC talks on YouTube, I came across this excellent talk by Jan Willem Nijman of Vlambeer on adding these types of elements to your game. I’d already implemented many of the techniques he talks about (camera shake, gun recoil, enemy and player knockback etc) but he made me rethink some aspects and put a bit more effort in to areas that were somewhat lacking.

So – here’s what I’ve been working on as the result of @jwaaaap‘s talk.

1. Bigger Bullets
To be honest a) this would never have occurred to me and b)I never would have thought it would work if it did. I was using little pixel squares for bullets as 1) they seemed appropriate for the size of gun and 2) this worked in Defender so why fix what ain’t broke? But I thought – ‘what the hell?’ and gave it a go. I started increasing the size of the bullets a little and was amazed how much better this felt, so I increased them what I would have thought was a ridiculous amount and it felt even better! It makes no visual sense whatsoever but the pistol (and particularly) the gatling gun are so much more satisfying to shoot now. I haven’t tried playing with the accuracy yet but should really do that too…

2. Camera Knockback
I already have some pretty hefty recoil on weapons but @jwaaaap suggests also recoiling the camera a certain amount when a weapon is fired. This didn’t make a massive difference in Jetboard Joust, probably because the camera is generally moving pretty fast anyway, but it is noticeable under some circumstances so I left it in.

3. Explosion Delay
Adding a very slight delay when an enemy is destroyed adds to the ‘jolt’ effect and makes destroying enemies much more satisfying. It’s subtle but it works. I’m using a delay of 32ms. I had to be careful here to not implement the delay until the next frame (ensuring the first frame of the explosion is drawn before the delay occurs) and also to clamp the delay time so that destroying a bunch of enemies at the same time didn’t result in a massive delay. I also improved the first ‘flash’ frame of the explosion by adding a ‘threshold invert’ to my collision shader and making the circles that briefly appear larger, brighter and less pixelated. Enemies really look like they’re getting nuked now!

4. Permanence
I had been wanting to do something to make battles seem more ‘permanent’ for some time and @jwaaaap‘s talk was the kick up the arse I needed. I talk about adding smoke in my previous post but that’s still not really permanent so I also added bones that fall from enemies when they’re destroyed and collect on the ground as a permanent record of the carnage that’s ocurred there.

Adding the bones was easy, the trouble started when I decided that they were too static and should react if the player hit the ground near them or crashed into a building that they were resting on. I didn’t want to run collision checking on every bone (there can be tons of them by the end of a level) so worked out a system whereby the world is divided into a series of overlapping ‘bone zones’. When a bone is static it is added to a zone and an entire zone can easily be discarded from the collision detection process in one go. I’ve used this approach before and it works well but I got myself into a bit of a flap with it here, plus it took a long time tweaking the various parameters so that the bones seemed to get disturbed by the correct amount. It still looks a little odd sometimes but its much better than having them totally static.

I’d really like to add some permanent damage to the buildings but I haven’t yet figured out a way to do this that would be a) be cpu/memory efficient and b) not involve creating a load more pixel art. I will continue to give this some thought – it could be that I’m underestimating the memory available on modern devices as a spent so long developing for J2ME feature phones!

So I hope that was all worth it and makes my game feel a little more like popping bubblewrap. I’d like to say these were the last gameplay tweaks before I release the alpha but watching my son play it has led me to implement just a couple more things…

Dev Time: 2 days
Total Dev Time: approx 99.5 days

previous|next

mockup_3x
My… What Big Bullets You Have!

mockup_3x
These Bullets Are Ridiculous – But Somehow They Work!

mockup_3x
Explosion Delay (Exaggerated), Smoke, And Improved ‘Flash Frame’

mockup_3x
A Battle Amidst The Bones Of Fallen Enemies

mockup_3x
Bone Bashing – A Stupid Detail That Caused Me Much Grief!

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

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

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 #52 – Go Logo!!

Been really ill over Christmas with a very heavy cold/flu and it hasn’t got any better this year as it appears to have developed into sinusitis. Now at least I know why I can barely walk up the stairs without feeling like my head’s going to split open.

So it’s been tough trying to work this week – but I’ve managed to get some done! It was quite a relief not to have to dive right into coding but to start with a fairly significant art task instead – the design of the game logo.

I had an idea of the type of thing I wanted but, as with all art projects, I started by gathering reference material and trying to whittle down ‘stuff I like’ into ‘stuff I like but might have a vague hope of achieving with my limited skills in a reasonable amount of time’.

I eventually settled on four key reference logos…

1. National Petrol
The ‘National’ brand is long-since defunct but I have fond memories of it from my childhood as National petrol stations were the only place in the UK that you could buy Smurfs! I really the the dynamism and simplicity of the main pictogram which has an almost Soviet constructivist feel.

2. Go Jetters – CBeebies
I’d never heard of this TV show (my kids are too old) but I was looking after my niece and nephew over the holiday and they had an activity book from the series. The ‘jet’ reference is obviously relevant and again I like the simplicity. The oblique effect on the type is subtle but adds a lot of dynamics.

3. Trans Am – Ultimate Play The Game
OK so this one’s kind of horrible but cool at the same time. As a kid the ‘Ultimate’ games were like the holy grail of Spectrum gaming. I originally looked at the ‘Jet Pac’ logo for obvious reasons but thought it too heavy and overworked. There’s more of a sense of motion to the ‘Trans Am’ logo and I like the ‘silver dream machine’ feel to it – even if that 70s airbrushed effect is something I’d normally avoid like the plague. It works in context.

4. Asteroids – Atari
I’m a massive fan of the Atari arcade service manual art but the trouble with it as reference is that it’s very intricate and would take more time and skill than I have at my disposal to pull off effectively. The nice thing about the ‘Asteroids’ logo is that it uses a very straightforward typeface in a pretty straightforward manner yet still works extremely well.

I decided to start working in Illustrator rather than Photoshop and to restrict myself to pure black and white. Restrictions are good – and I knew that if I had something that looked good in a single colour it would be easy to add colour later whereas trying to retrofit a colour logo into black and white can be a nightmare. It’s a similar approach to the one I’m taking with the actual game art.

Once I had my reference in place I began experimenting with different typefaces*. Initially I thought I needed something that looked a bit ‘sci-fi’ but, despite finding some nice fonts, everything I tried looked either incorrectly proportioned or too gimmicky. The only typeface that seemed to hit the spot was Helvetica Neue Black Oblique which is very similar to the font used in the Asteroids logo. I rotated the letters anti-clockwise so that the uprights sat directly vertical, spaced the letters very tightly (so much so that some of them joined together) and finally felt like I had something I could work with. I also sheared the logo slightly so that it sat at an exact 25% gradient in order to make it easier to convert to pixel art.

Next step was to add something to make the logo seem more unique and give it more of a feeling of motion. I started by add some ‘wings’ to the tops of the ‘J’ characters based on the ‘winged helmet’ of the National logo. This worked right away! I tried some more curvaceous and illustrative alternatives as well but these all seemed too flouncy so the hard-edged brutalist approach won out ( a good job really as it would be a whole lot easier to realise as low-res pixel art). I also added similar ‘wings’ to the right side of the logo which seemed to balance better.

I then tried to increase the motion effect by adding Dyno-Rod style arrow-type shapes at the top-left of letters where there was a lot of negative space. As well as making the lettering seem more dynamic this also had the benefit of filling in the negative space, thus making the letters seems as if they were spaced more evenly.

Lastly I felt the logo needed something to kind of tie it all together a bit more so I experimented with various ‘underline’ effects and illustrative elements, eventually settling for a simple ‘double underline’ consistent with the National-style ‘wings’ on the letters. It doesn’t look like it but the little angled section on the right of the underline took a long time to get right!

Once this was in place I noticed that the ‘wings’ gave the type an almost 3D effect – I liked this (for some reason it reminded me a bit of the 20th Century Fox logo) so I tweaked the angles and lengths to exaggerate the effect.

At this point I was pretty happy with the vector version so I moved on to converting it to low-res pixel art. I began working at a resolution of 256 pixels wide as this seemed to scale nicely for the title screen.

The most time-consuming stage of creating the pixel art version was tidying up the original, rasterized, black and white version so that it looked as good as possible. I realigned all the angled lines so that any that run parallel ‘step up’ at the same time and also changed the angle at the end of the ‘wings’ so that this ran at 45 degrees which looked a lot tidier and didn’t really seem to affect the overall feel.

After this it was a matter of playing around with outlines, drop-shadows and highlights in Photoshop until I found something I liked then tidying it up manually. The final stage was to add some ‘shine’ to the letters (a bit like the ‘Trans Am’ logo) and a final bit of texture by manually dithering the edges of the ‘shine’ and adding some rivets.

I’m pretty pleased with the end result – it looks clear, dynamic, and has a kind of accidental retro/art-deco sci-fi quality that I like. Reminds me of ‘Flash Gordon’ or some of the work by French comic artist Moebius, neither of which are reference points to be ashamed of. The pixel art version could still do with more texture (possibly) but it was hard to do this with the limited palette I’d set myself, and these things can always be better so maybe I’ll revisit at some stage – for now though it’s time to get it integrated into the game!

* Whilst doing this I came across this really useful tool – it’s like Shazam for fonts and actually works (did for me anyway)!

Dev Time: 2 days
Total Dev Time: approx 93.5 days

previous | next

mockup_3x
Gathering Reference Material

mockup_3x
Unsuccessfully Experimenting With Typefaces

mockup_3x
The Final Flat Vector Version

mockup_3x
The Final Pixel Art Version (Click To See 2:1)


Two Day’s Work In Ten Seconds

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 #50 – Sound Thinking!

Woohoo – it’s my 50th DevLog!! Sadly no-one is throwing me a party (or any money).

Just been finishing off the final pieces of missing audio for the alpha version. As before I’ve done everything using the DSI Tempest and a couple of fx processors – namely an ancient Boss RV-1000 reverb and, this time, a Pigtronix Echolution 2 on delay duties.

The only one that caused an issues was the ‘combo’ effect – I wanted an arpeggio-style sequence that played for longer depending on how much of a combo was awarded. Pretty easy to build the audio from a series of separate notes and step forward each time another enemy is destroyed in the combo ‘chain’, harder to stop several notes from all playing at once if several enemies are destroyed simultaneously (ie with a single shotgun blast).

So I built a ‘SequenceAudioPlayer’ class that steps forward in the sequence each time Play() is called but that queues notes to be played after a set interval if Play() is called too quickly. This way I get a nice ascending arp even if multiple enemies are dispatched at once.

You can hear a bunch of the new sounds (as well as some of the old ones) in these short gameplay vids.

Dev Time: 1.5 days
Total Dev Time: approx 84.5 days

previous | next