Monthly Archives: April 2016

Jetboard Joust Devlog #27 – Bang Go Some Bugs

Bit of a ‘clearing the decks’ session today as I get rid of a few bugs that have been irritating me. There were problems with the teleport sequence that I needed to fix (the jetboard weapon attachment not getting displayed correctly), the ‘lost the jetboard’ sequence was annoying me (as the main character carried on waving his arm all gung-ho even when it was obvious he was heading for certain death) and I needed some kind of explosion/disintegration effect for a destroyed jetboard.

None of these proved particularly heinous to sort thankfully so I could move on pretty quickly to tweaking the enemy explosions which I wasn’t entirely happy with. I wanted something a bit more dramatic but not too OTT and think I got there in the end – though my first attempts were way to extreme. Took a fair bit of tweaking though.

I tried adding a velocity deviation to the particles in the enemy explosion but I think I prefer it with the particles moving at a more uniform velocity. It’s not ‘realistic’ but it seems to fit with the visual feel to me, slightly more glitchy and geometric in quality.

Dev Time: 0.5 days
Total Dev Time: approx 29.5 days

previous | next

mockup_3x
Improved ‘Lost Jetboard’ – Not So Gung-Ho Now!

mockup_3x
Too Much ‘Shock And Awe’ For George W Bush Even?

mockup_3x
Toned Down – Almost There

mockup_3x
Final(!?) Explosion – More Uniform Particles

Jetboard Joust Devlog #26 – Pistols At Dawn

So – with the AI now looking respectable it’s time to get the first basic weapon in there!

I should add that before doing this I did improve the AI a bit since the last post – instead of just charging ‘through’ the player when moving to a safe distance it now makes an attempt to fly over or under instead. This looks a lot better, particularly when going ‘face to face’ on the ground and between obstacles.

The most basic weapon, other than the jetboard jump, is the pistol (has to be). Implementing a simple pistol shot should be easy but it took me rather a long time as, as ever, I started obsessing over the details. I started with a simple two pixel square as the bullet (that’s all the room I have to play with really) but wasn’t very happy with it so began using a simple particle effect to create a type of trail instead. This looked much better but when the entire trail disappeared at the end of the bullet’s range it looked rather odd so I had to implement a way to have the trail carry on moving and disappear at the same place as the ‘main’ bullet. Doing this in an efficient manner (ie not by creating loads of separate sprite objects) was a bit of a pain in the arse – I also had to think about what would happen when the bullet collided with an obstacle too.

Got there in the end though – and added a simple particle effect for when the bullet disappears or explodes. When everything slotted together it looked quite satisfying – like fireworks.

I also added a bunch of generic parameters that will apply to every weapon and affect the speed at which a weapon can be fired – these are:

Automatic
Whether the weapon auto-fires when FIRE is held.

Repeat Rate
The quickest speed at which a weapon can be fired in succession.

Clip Size
The amount of ammo that can be fired before the weapon needs reloading.

Reload Time
The time the weapon takes to reload (doh)!

I think that should give me enough configurations to play with – reloading will happen automatically if enough time is left between shots.

Once all this was sorted getting the enemy AI to fire was pretty straightforward as all the board/weapon code is the same for both player and enemies. At the moment it just pumps FIRE when within a certain range of the player so I need to add some kind of reaction time parameters but it’s pretty effective.

Maybe rather too effective – an unexpected accident was the way the enemy keeps pumping the player full of bullets even after they’re dead ‘just to make sure’. I actually think this is pretty funny so will probably leave it in there – makes the enemies seem ultra vindictive and evil!

I need to tweak this a bit and iron out some other bugs that are annoying me next – then it’ll be on to creating ‘cash’ pickups when enemies are destroyed.

Dev Time: 1.5 days
Total Dev Time: approx 29 days

previous | next

mockup_3x
Improved AI To Circumnavigate Player More Effectively

mockup_3x
Shock And Awe? The Final Bullet Anim


A Very Vindictive AI – I’ve Created A Monster!!

mockup_3x
Pistols At Dawn – Proof That Violence Solves Nothing

Jetboard Joust Devlog #25 – A Fine Line Between Stupid And Clever

Now I have my basic jetboarding enemies in place it’s time to start turning them into something that actually constitutes opposition – that means AI.

Fortunately we’re not talking neural networks here. To quote Spinal Tap (again) ‘It’s such a fine line between stupid and… clever’ and we just need something that operates well enough to track the player reliably and reasonably realistically.

So I started with a basic premise – at preset intervals (call it ‘reaction time’) the enemy would make a decision as to whether to operate their horizontal and/or vertical thrusters based on what the player was doing. There would be a configurable horizontal and vertical reaction time for different enemy types, as well as a configurable ‘aggro distance’ outside of which the enemy would just idle rather than attempting to attack.

The first and most basic decision making I tried was extremely simple, just move in the direction of the player and hope for the best. I tried this with a reaction time of 1/10th of a second and it actually worked surprisingly well. There were a few key problems however.

1. The Kamikaze Effect
A result of this super-simple decision making is that the enemy just charges headlong into the player. This might be appropriate for certain enemies but most should really hang back at a reasonably safe distance. In order to resolve this I added a ‘range’ parameter to the jetboard weapon attachment – now if the enemy is within weapon range of the player they don’t attempt to move any closer.

2. World Wrap Confusion (He’s Behind You)!
Dealing with a wrapping scrolling world can be a pain at the point the world wraps. Say my world is 1000 units wide, player is at x location 950 and the enemy is at x location 50 – onscreen this appears as if the player is to the enemy’s left though as far as the coordinates are concerned he’s way off to the right! The solution here is to offset everything by the player’s x location (ie treat player x as zero) and then ‘wrap’ the resulting enemy x location (if it is less than world.width/2 add world.width, if greater than world.width/2 subtract world width).

3. Getting Over It
This one’s a slightly trickier problem. Making the enemy fly over obstacles instead of getting blocked by them is straightforward (if the path is blocked, activate vertical thrusters – job done) but the issue is complicated when also trying to maintain a safe distance (weapon range) from the player. Maintaining a safe distance is pointless if we do not have a clear line of sight to the player in order to fire a weapon. The solution here is to draw a rectangle between the enemy and the player – if this rectangle intersects any obstacles that are higher than the player then we need to get past them (activate horizontal thrusters), if these obstacles are higher than the current enemy position we also need to get over them (activate vertical thrusters).

By this point the AI was performing pretty well – enemies would chase the player down (even across the world wrap), not get stuck on obstacles and (most of the time) maintain a reasonably safe distance from the player from which they would be able to fire weapons. There were a couple of things still niggling me though…

4. Not So Fast!
Up to this point I had been treating the use of the horizontal thrusters as pretty binary, ie just on or off depending on the position of the player and obstacles. Whilst this worked most of the time it meant enemies had a tendency to accelerate extremely rapidly and then not have enough time to slow down, therefore overshooting or colliding into the player. I have tweaked this so that enemies only accelerate when close to the player if below a certain speed or if the player is moving away from them. This results in much better tracking and also and apparent ‘feathering’ of the thrusters which looks more realistic.

5. Getting Away From It
Even with the all the above there were still instances in which the enemy would end up aligned with the player on the horizontal axis and, unless the player moved away, just attempt to collide with him. I needed to extend my concept of a ‘safe zone’ so that, not only did the enemy stop moving towards the player when it entered the safe zone, it actively moved towards the edges of the safe zone when too close to the player. I implemented this with the additional constraint that, when too close to the player, the enemy moves away from the player in the direction of the furthest obstacle from the player. This seems to work fine.

No doubt I will refine aspects of the above but for now I think I have a pretty convincing AI controlled jetboarder. Next step is to create the first basic weapon..

Dev Time: 1.5 days
Total Dev Time: approx 27.5 days

previous | next

mockup_3x
First Attempt – The Kamikaze Effect

mockup_3x
Confusion At The World Wrap Point

mockup_3x
Get Over It, Stupid!

mockup_3x
Learning To Circumnavigate Obstacles

mockup_3x
From Stupid To (Relatively) Clever

Animated GIFs of Gameplay Footage for Twitter on Mac OSX

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

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

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

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

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

So, in detail…

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

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

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

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

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

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

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

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

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

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

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

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

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

Jetboard Joust Devlog #24 – It’s All About Class

I want to have enemies on jetboards.

I didn’t really think about this at first – I thought that the enemies would be your usual SHMUP fare, different types of robots/spaceships and the like. But as the game’s called ‘Jetboard Joust’ it makes more sense to have at least some of the enemies riding jetboards like the player.

I’d also been thinking about the rpg-lite elements to the game. There’s going to be different ways to arm your jetboard and a weapon upgrade system – if I treated the enemies and jetboards differently I’d end up with far more combinations of opponent which would make things much more interesting. I guess its been Dark Souls (again) making me mull over this – the way the same basic enemy can present a very different challenge depending what weapon they’re armed with and what armour they’re wearing.

So I’ve been pulling apart my class structure to get something that’s much more flexible. First step was to create a generic ‘Board’ and ‘Rider’ class that represent, at the most basic level, a board and something that rides it. I then created the (somewhat randomly named) Surfer class which defines a Rider that animates in a similar way to the main player character (based on a 3×3 grid as described here). I split out a separate Jetboard class which extends Board – this contains the code for the ‘jetboard as weapon’ functionality which will probably only be available to the main character (as I think having enemies jumping off their jetboards will become too visually complex and confusing). There’s also a separate Weapon class which represents the base level weapon attachment for a board.

The fly in the ointment was with the enemy classes. There’s a bunch of generic ‘enemy’ code that deals with things like player collisions and collisions with projectiles. I couldn’t find a way to share this between enemies that were subclasses of Surfer and those that weren’t (ie won’t be riding jetboards) so I’ve had to (annoyingly) duplicate some of this in the EnemySurfer and GenericEnemy classes. There’s an IEnemy interface that allows both of these to be treated generically by various methods. Not having multiple inheritance is both a blessing and a curse sometimes.

Oh yeah, the base level Character class defines something that has health and can collide with the player and/or projectiles.

This all took some time – I hate retrofitting class hierarchies – but I took it slowly and carefully and once I was all done everything (amazingly) worked fine apart from one minor bug which was fairly easily quashed.

I’ve also designed my first jetboarding enemy – calling him ‘Skullhead’ for now.

Next step will be to add some basic enemy AI and get weapon attachments working.

Dev Time: 1.5 days
Total Dev Time: approx 26 days

previous | next

mockup_3x
The New Class Hierarchy

mockup_3x
Very Basic Jetboarding Enemy In Action

Jetboard Joust Devlog #23 – Spinning Crate Gate

Finally got the spinning crate sorted thanks to some pointers from very helpful Twitter user @grayhaze.

Seems obvious when you think about it but really the cube should get wider whilst it spins, not narrower as I had it (unless the perspective was ridiculously exaggerated). Another good tip from @grayhaze was to try drawing things from the top when approaching problems like this – if I’d have done that in the first place I wouldn’t have wasted anything like as much time.

So with that in mind I was able to create a ‘flat on’ spinning crate without having to add any perspective – and it doesn’t look like a page turning!

Next task was to actually make the weapon swap happen which, whilst pretty straightforward, involved a lot of setting up of additional classes and code restructuring so was fairly time consuming – note the way the weapon attachment on the jetboard changes in the GIF on the right.

I’m glad this has been put to bed now. Now I need to do some proper work on the enemies which is going to involve even more code restructuring (groan) so you may well not hear from me for a while…

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

previous | next

mockup_3x
It Should Get Wider, Stupid!!


Weapon Exchange Sequence Finally Done