Category Archives: Jetboard Joust

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

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

Jetboard Joust Devlog #22 – Spin Doctor

Don’t you just hate it when something that you thought would take a couple of hours takes pretty much all day – and then you’re still not entirely happy with it?

Witness the spinning crate. A bit of a repeat of the floor tile episode this one – and another indicator of just how inexperienced I am with pixel art.

I needed something for a ‘weapon swap’ pickup. As it’s a swap (ie your original weapon gets left behind and a new one picked up) I needed a kind of ‘permanent’ storage system rather than something that gets destroyed on pickup like the bubble I’m using for extra health.

A crate seemed the obvious choice. Far from original I know, but it seemed as though it worked work and there’s something quite iconic about the pickup crate. I thought the crate could spin when you activated it and the crate icon change to show the weapon you’d just deposited.

Designing the crate itself was pretty easy. Getting it to spin wasn’t. Firstly I made the schoolboy error of drawing every frame of the animation before prototyping it. Each frame looked great on its own but when I tested the animation I was gutted to discover I’d failed miserably. The crate didn’t really look like it was spinning – it looked like the pages of a book turning or something. Everything I’d done ‘should’ have worked (to my mind) and I was somewhat stuck to figure out what I’d done wrong.

So I did what I should have done in the first place if I’d have had half a brain – I went back to the drawing board and sketched out some simple prototypes. This (and studying a few classic ‘spinning cube’ demos) enabled me to see where the problem was. My art style is fully 2D which means that, really, there should be no perspective. However it turns out that without perspective it’s very difficult to judge what is ‘3D’ and what’s not (hence the ‘page turn’ effect). I tried adding some shading and this helped but the only way I could get the crate to look like a cube was to add some simple perspective. I think, really, this shouldn’t fit with the art style but it does seem to kind of work to me. I could only add perspective to the top of the crate though, otherwise it didn’t sit right on the ground!

Another issue which compounds the difficulty is trying to work with a strict eight colour palette (this makes gradually altering the brightness of things very difficult) and working in a ‘blown up’ pixel style. In most instances every pixel I use will be represented by at least three pixels on screen so a one pixel shift in the artwork actually represents quite a visual ‘jump’. In the (for now) final animation I only use a one pixel shift for the perspective and it almost seems too much (that’s right, ‘too much f-ing perspective’ to quote spinal tap).

In the animated GIF on the right you can see some rough prototypes followed by the ‘final’ animation as it stands at the moment.

1. The first approach – looks like a ‘page turn’
2. Adding shading – slightly better but still looks like a page turn.
3. Adding perspective – starting to look like a cube now.

Anyway – what doesn’t kill you makes you stronger and all that. The moral of today’s story kids is simple prototypes first!

Maybe I should have titled this post ‘Spinning Crate Gate’.

Dev Time: 0.75 days
Total Dev Time: approx 23.5 days

previous | next

mockup_3x
The Static Crate Design – This Is The Easy Part

mockup_3x
Getting Things In Persepective

Jetboard Joust Devlog #21 – HUD’s Up!

Designing a game HUD is one of those things that always feel a bit of a drag to me. It’s not very exciting, not really part of the gameplay, and when it comes to coding often requires a lot of tedious repetition. You know the sort of thing – when you know exactly what you need to do and how to do it it’s just that it’s going to take a lot of typing to get there.

On the plus side, often when the HUD is added your game starts to feel much more like a game rather than an elaborate demo of some kind. This is good!

I spent a fair bit of time messing around with alternate layouts for the Jetboard Joust HUD. I’m pretty sure what type of info I want in there – obviously score and lives but also your currently selected weapon and the amount of ammo for it. It was tough to get everything in there whilst still remaining visually balanced and leaving enough space for the scanner.

I liked the idea of pretty big digits for the score and wanted something that looked vaguely ‘sci-fi’ whilst still being readable. In the end I designed my own font for this (though it was heavily based on Space Odyssey). For the small text I used the excellent 04b24 which is (with the exception of the letter ‘i’) a monospaced bitmap font.

I think it looks pretty good. The one thing I’m not sure about is displaying the amount of lives on the right-hand side. I’d rather have kept this area just for weapon info but as I can’t really think what else I might put in there other than amount of ammo and currently selected weapon it was looking rather empty.

Couldn’t end this post without a shout out to two of my favourite game HUDs…

Firstly the scroll from Ultimate Play The Game’s wonderful ‘Atic Atac’. Ultimate were pretty much experts in the art of taking up most of the screen with an elaborate HUD so that they could push the refresh speed in the little amount of screen real estate that remained for the actual game – ‘Gunfright’ being a great example. The ‘Atic Atac’ HUD though, with its roast chicken that gradually gets picked to the bones as your health depletes and its completely pointless ‘scroll’ legend remains an absolute classic.

And secondly the HUD from ‘Dead Space’ which, rather than take you to a separate screen, is actually projected into the game environment from your super-advanced tech helmet (or whatever it was called). This was a great way of presenting complex information to the player without disconnecting them from the game experience. Shame the game experience itself was so clunky though – I still shudder at the thought of that dreadful ‘Asteroids’ style minigame…

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

previous | next

mockup_3x
HUD Elements In Close Up

mockup_3x
HUD in game (click for a closer look)

mockup_3x
Getting A Roasting In Atic Atac

mockup_3x
Gunfright – More HUD, Less Game

mockup_3x
Dead Space – Nice HUD, Shame About The Gameplay

Jetboard Joust Devlog #20 – Got Health

Working on health pickups today – that means more pixel-pushing! Fortunately the health pickup itself was pretty straightforward. I wanted a spinning ‘First Aid’ type icon inside a bubble – the hardest thing to get right here turned out to be getting the spinning icon to look like it was inside the bubble whilst remaining legible and also sticking to minimal palette.

My solution in the end was (in Photoshop) to duplicate the bubble layer and place on top of the icon. Set the new overlaid layer to ‘screen’, reduce opacity considerably, delete everything bar the highlights and then apply the icon layer as a mask. This has the effect of only applying light highlights to the icon itself. It’s a bit of a cheat as I’m creating colours not in my original palette but it works and looks pretty good. I may have to revise this a little if and when I come to apply different palettes to the game.

Whilst designing this I couldn’t help but wonder how many pixel-pushers before me had designed health pickup icons – there should be some kind of repository of them somewhere!

Integration into the game was pretty straightforward as well, time consuming as I needed to set up a new ‘pickup’ superclass to handle collisions with the environment and manage getting collected etc but nothing overly complex. Designing the ‘collection’ animation took a bit longer, mainly tweaking the bubble particles that appear but drawing and animating that concentric ring effect took some time as well. Again – not difficult, just time consuming. I’m pleased with the end result though.

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

previous | next

mockup_3x
Got Health – No Jogging Required

Jetboard Joust Devlog #19 -When ‘Correct’ Just Ain’t Right

Usually when working on in-game physics and stuff the best place to start is with what would be ‘correct’ in the real world. I only have a physics ‘O’ level (and that was a very long time ago) but that’s generally enough to get me by in the world of 2D gaming.

Sometimes though, what would be ‘correct’ in the real world just looks ‘wrong’ in an in-game context – and here’s an example.

In the first image, if you can see make it out, you’ll see that when the jetboard hits an obstacle the ‘blast’ sprites and particles carry on past the jetboard when it stops – this is because they are ‘correctly’ initialised with the same velocity as the jetboard. In practice though, this looks pretty stupid. I guess I could run collision detection on the blast sprites and particles and have them also collide into the obstacle (this would be ‘correct’) but that would be pretty impractical, particularly for the particles – I also think it would still look kind of weird.

So what I’ve done instead is make the blast sprites and particles always move relative to the jetboard, therefore their velocity slows down and speeds up as the jetboard does. Even though far from physically ‘correct’ this looks much better in a 2D gaming context.

Dev Time: 0.25 days
Total Dev Time: approx 20.75 days

previous

mockup_3x
Physically ‘Correct’ – Looks Like A Bug

mockup_3x
Physically ‘Incorrect’ – Looks Much Better

Jetboard Joust Devlog #18 -Enter The Warp Gate

Wasn’t working much on Jetboard Joust last week – had to do an ad-free update of Flapping Bird for a distributor (yes, I did a ‘Flappy Bird’ clone – the shame)!

Anyway – back onto it this week and I’ve been doing more custom shader stuff, this time for the ‘level complete/next level’ cycle. I wasn’t looking forward to this to be honest as I thought it would be a really fiddly process but actually it went OK.

What’s going to happen when the level is complete is that a kind of ‘warp gate’ appears – enter the warp gate and you get transported to the next level. I wanted the level to disintegrate into pixels in much the same way the main character does when teleported in/out (see previous post).

The first thing though was to actually design the warp gate itself. I wanted something that felt a little ‘sci-fi’ and also a little ‘primitive’ to fit in with the ruins. I looked at various things for inspiration, not least the ‘hub portals‘ from ‘Turok – Dinosaur Hunter’ on the N64 (remember that game, it was ace!) which hold very fond memories for me. This page of concept art from Destiny was also a big influence.

I wasn’t too tough to arrive at a design I liked – and animating it (though very time consuming) was also pretty trouble free. I then spent quite a bit of time tweaking some particle fx to go with it – trying to keep a ‘pixelly’ feel. I’m really pleased with the end result now.

Implementing the ‘pixel dissolve’ for the entire level meant using a custom shader for ‘post-render’ fx. This was another first for me but fortunately pretty simple to implement. Rather than drawing the game world to screen I draw it to an offscreen image (RenderTarget2D in MonoGame) and then apply the shader when rendering this offscreen image to screen. As if often the case with this stuff, the hardest part is tweaking the tweens so that the dissolve feels ‘right’. I think it’s OK now but there’s still something bugging me about the ‘fade in’ a bit. I used the same shader I wrote for the teleport fx as described in the previous post.

Then it’s a matter of sequencing everything together which I have now done, though this procedure is too long to get across in an animated GIF…

1. Complete level
2. Warp gate appears (using teleport shader) –
3. Enter warp gate
4. Main character teleports out
5. Old level dissolves out
6. New level dissolves in
7. Main character teleports in

If you’re being observant you’ll notice that I’ve made the particles on the player teleport rather more ‘pixelly’. I’ve also updated the die/retry loop from the pipes of old to a new version using the teleport effect.

Next up will be some work on pickups and changing jetboards.

Dev Time: 2 days
Total Dev Time: approx 20.5 days

previous | next

mockup_3x
The Final Warp Gate Design With Particles

mockup_3x
The Level Exit/Enter Dissolve Effect

mockup_3x
Entering The Warp Gate And Leaving The Level

Jetboard Joust Devlog #17 – Beam Me Up, Dotty

More going over old ground as the game starts to develop it’s own visual style. It’s annoying but necessary – one has to take an organic approach to these types of things I think. Really I should stick with placeholder art and work on the design almost completely separately from the gameplay (as if I was working with another artist) but I find it very hard to do that. Consequently I’ve wasted at least two or three days so far which is kind of frustrating. Hey ho!

Anyway, the latest thing to be redone is the new life/appear animation. I did have the main character being shot from a Mario-style pipe as you’ll see here but that didn’t really seem in character any more. I wanted something more spacey and in keeping with the feel of Defender which is my main inspiration for Jetboard Joust.

So I started work on a ‘teleport’ effect. I knew I wanted the main character to dissolve into a kind of pixelated fog and the most appropriate way to achieve this seemed to be through a custom shader – down the HLSL rabbit hole again.

I started by creating a shader that reduced the pixel resolution of the drawn texture. I split the texture into a series of chunks and took a sample from the centre of each chunk which was returned as the colour to draw. Having no HLSL experience it took a while just to get to this stage. I have all my animations on sprite sheets so each sprite drawn is generally a small portion of a much larger texture, HLSL works with coordinates relative to the full texture (regardless of the region being drawn) so initially the results I was getting were pretty random (when they weren’t completely blank) but when I figured out to pass the coordinates of the cropped region to the shader and do my calculations based on that instead things started to progress pretty quickly.

Initial results were promising (though somewhat static) and the effect looked like something I could progress with. I added some motion by sampling from a random point in each chunk rather than the center (I do this every other frame) and a kind of ‘spark’ effect by inverting the colour balance every so often (currently every four frames). I also added the ability to sample from a smaller portion of the texture than that being drawn, effectively scaling up the sprite. Then I added the ability to set the alpha for the entire shader allowing it to fade out smoothly.

We were getting there now! This was all the functionality I really needed from the shader and the next stage was setting up some tweens in my main game code to control the various parameters. There’s quite a few tweens chained together in the final result, one controlling the sample size, one the scaling and one the transparency. I wanted it to look like tuning into a radio station sounds with big adjustments at the start (no reception) and small ones at the end (finding the point of best reception).

Once I was happy with that I added some more particles, trying to keep things fairly stylised looking. A small change to the particle generator was required to allow for imploding particles. There’s also a pixel particle generator which blurs the edges of the actual texture (this looked a bit too obviously square at low sample sizes).

And now I think almost done. Only thing that’s really bugging me is the very dark pixels from the shader when they get large, these look a bit too glitchy (not in a good way). May have to knock these back a bit or something. And there’s something about the small explosion/implosion particles not quite sitting right with the larger pixels – I might need to make these particle fx more ‘pixelly’ somehow…

One HLSL thing that had me stumped for a while was that, whilst I was tweaking and commenting out bits of code, the C# code that set an effect parameter in the shader suddenly started throwing a null pointer exception indicating that that parameter was no longer present in the shader. WTF? Turns out that, though I hadn’t removed the parameter declaration in the shader, I’d removed all references to it in the actual code so the compiler was optimising it out (doh)!

It may also interest you to know that I did all this thinking ‘Defender’ had a similar ‘implosion’ effect when the player’s ship appears – but it turns out it doesn’t at all – neither does the sequel ‘Stargate’! Damn childhood memories deceiving me.

Dev Time: 0.75 days (including project setup)
Total Dev Time: approx 18.5 days

previous|next

mockup_3x
Attempt #1

mockup_3x
Attempt #2

mockup_3x
Attempt #3

mockup_3x
Attempt #4 – Almost Done(!)