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

First Attempt – The Kamikaze Effect

Confusion At The World Wrap Point

Get Over It, Stupid!

Learning To Circumnavigate Obstacles

From Stupid To (Relatively) Clever

One Trackback

  1. […] I didn’t really run into any issues I hadn’t come up against already when writing the ‘chase player’ code though so thankfully I could pretty much reuse the techniques I’d come up with there and blogged about earlier. […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: