More Complicated Hunt AI

SMARTER HUNTING AI

In my previous post I talked a bit about my plan for AI chasing for a rolling ball game. I covered three separate targets to make AI smarter.

Dumb: Go after the player’s position.

Well, by the time you get there, player may well be long gone. He used to be there.

 

Smart: Go after the player’s future position based on his current velocity. Better.

However, if the player is trying to change direction with joystick, he’ll still be gone when enemy gets there, as he is not going in a straight line, but curving to a new position:

 

Smarter: Go after the player’s intended position, based on current velocity plus joystick’s direction. This means the enemy is heading towards where the player is hoping to be.

This is a pretty smart algorithm, but there is a problem depending on how fast the enemy is. One of the factors that you can tweak in making an AI enemy “better” is just by making it faster, dumber would be slower. However, at some point, the enemy will begin to race ahead of the player if it’s too fast. And I’ve tested this. If my player just goes in a straight line for a while, the enemy races right on by and says “Hey, I’ll meet you up here!”

“Hey, you were supposed to be here. I guess I’ll wait?”

There must be a better way still!

 

LERP BETWEEN TARGETS

So I had a thought:

What if the enemy tries to get to the player’s intended position if the two are far apart, but as the two get closer, the enemy’s focus slides towards the player. That means that as the two close the distance between themselves, the enemy goes more for the player’s current position and less for a future position!

(A LERP (linear interpolation) is simply a slider between two positions, based on a percentage, which can change on the fly. 0% focuses on the first target’s position, while 100% focuses on the second target’s position. Percentages in between focus proportionally.)

This sounds awesome!

1) I already have a MODE switch, between target = player; target = player’s velocity position; target = player’s intended position (velocity + joystick)

2) Keep track of the target’s position. This can be either player, velocity or intended, see above.

3) Keep track of a second position: This will always be the player!

4) Get an interpolation between these two angles based on a number between 0 and 1 (a Mathematical LERP). If mode is targeting player, nothing changes, as a lerp between two same values will always be that value.

5) Keep track of the distance between the enemy and the player. Cap this at some maximum and divide that distance by the cap. So if 10 meters is your max, and there is 30 meters between the two bodies, it still just uses 10 as distance. Divide by cap and the number will be 3 if distance is 30, or 1 if distance is 10.

6) Clamp this value between 0 and 1. That way, any distances greater than 10 won’t make a difference. But at 10 meters, the enemy is aiming towards the target (velocity or intended). At 0 meters, the enemy is aiming all at the player. And of course half-way there, it’s half-way.

If the Hunt Mode is set to player you will see no difference because both of the targets will be the player, and any Lerping between them gives the same result, so no change there.

However, for velocity position and intended position you get a sliding focus between the two targets.

And … I just tested it. It works rather well.

Here, the player and enemy are far apart, so the enemy targets the intended position 100%:

 

Soon, as they get closer together, the enemy begins to target 2/3 to the intended position and 1/3 to the player: (this slides, obviously. I’m using thirds to illustrate.)

And as the player gets even closer along that path, his focus slides even more towards the player. Here, you see it 1/3 towards intended position and 2/3 towards player:

And even closer still, the enemy now focuses entirely on the player, and not at all on the intended position:

This works pretty well in practice.

This is what it looks like over time:

However, it’s difficult for the enemy to catch the player at all times. The player can fairly easily evade the enemy because the enemy has momentum. If it’s pushed for some time towards a predicted position, then the player suddenly changes direction, so to does the enemy, but it does take some time, due to the momentum, so it may shoot right on by and then arc back to take up the chase again.

But then… that’s kinda what I want.

And each parameter in this scheme is variable.

The distance along the velocity vector can be short or long, which would alter the perceived intelligence of the Hunt AI

The distance along the joystick vector can be short or long, which would also alter it

The force the enemy is exerting towards its target can be mild or strong. This is a major factor in how “smart” it seems

The mass of the enemy matters too. If it is less massive, it can turn on a dime, whereas a heavier enemy will have to take more time to swing back around if it misses.

Each of these parameters can be set on the fly by a game, as it determines how smart it wants an enemy to be, whether that be level, or a timer, or whatever.

 

ATTACK!

My next step in this scheme is to set a radius around the enemy, and if the player gets inside that radius, the enemy is going to exert a very strong sudden impulse towards the player, which is basically a punch attack!

I will post stuff when I get that working.

 

Predictive Chase AI for Unity

Many years ago now, I designed a game on paper for iPhones. I never built it. Never new how.

However, now that I have gotten familiar with Unity I have been able to write parts of this game, as time permits. And as you can see from reading below my time is spread out pretty thin among my many interests.

That said, I managed to make a very playable as-yet-incomplete Hover Taxi game that I will write much more about in future.

But for now, back to my Rolly Ball game. Based on a game I wrote in BASIC on the Commodore 64, which was based not-so-loosely on Q*Bert, but with a level editor, I decided to make a game where you control a rolling ball with accelerometer. I haven’t quite cracked that part yet, so for now I’m using an XBox 360 controller and it works fine.

So far I have the ball rolling around changing the color of grid tiles. That’s the main game.

But there has to be more. Much more.

Enemies

Enemies start out pretty docile, just meandering around the board undoing your work, repainting squares back to their original colors. You have to stop them by hopefully pushing them hard enough to break them, or push them off the board if I allow that. (A no-edge board presents major problems for a player.)

Later, enemies begin to chase, and eventually get quite aggressive in not only chasing you but predicting where you are going and getting there first, and even adding a sudden pulse to push you suddenly in a different direction.

How Do I Make An Enemy Hunt?

I started a totally new Unity project to explore this AI idea:

The Player is a spherical rigidbody. That’s a physics object that can roll around and obey the game’s physics laws. To make it move, I use an analog joystick pad to add impulse in the direction the joystick is pointing, at the force the analog joystick is pointing. (ie: you can nudge the stick and get a small push, or jam it all the way for a larger push.)

So that’s been done for months.

But what about an enemy ball? How do I get it to be a threat?

Just telling the enemy ball to try to get to where you are at this very moment is not so great. By the time it gets there, you’re long gone.

So I set up a scene in which an indicator circle is placed at the Player’s velocity vector. That is, an X, Y, Z coordinate which indicates where the ball is going at any given Physics Frame.

If I set the enemy up to try to get there, by adding an impulse in that direction, that will be better. It will get to where you’re going. However, you’re not just rolling in a straight line.

You have a joystick to tell your Player ball you now want to head off in a different direction entirely, and because physics has momentum, you don’t suddenly go in that direction, but you angle towards it naturally.

So now I add another vector of the Joystick’s intended direction, and I add that vector to the position of the ball’s velocity position.

To visualize this, I created two indicators.

One is placed, every frame, at the position the ball’s velocity wants it to go.

The other is placed relative to that object, in the position of the joystick’s vector.

Each of these values is multiplied by an intensity variable, so I can tweak how much to tell the Enemy ball the player wants to get there.

I used two line renderers to draw lines between the objects so you can easily tell what the motion vectors are.

Here’s a screenshot to tide you over until I fill in the above with better shots when I get time.

Why No Updates?

Well first, updates were never very regular. But this time I just got burned out.

Toylanta

In what was supposed to be a great experience, I booked a trip to Atlanta for Toylanta, a toy collecting show that started as an alternative GI Joe Collectors’ Show, as an option for those who could not or would not attend the official GI Joe Collectors’ Club Convention.

I was lucky enough to attend two of those, one in Providence, because it was just down the road, and one in Dallas which I went through great pains to go to.

I loved both.

But since the Collectors’ Club shut down, I figured this would be a great opportunity to attend Joelanta (now Toylanta) and see a lot of people who have wanted me to go for many years. Friends I knew only online.

And I did meet many of my good friends there, and had a great time. And met many good new friends.

But the show kind of overwhelmed me.

Burnout

It put me on the back foot. It drained me. It should not have drained me. It should have invigorated me. But it drained me instead.

From March to mid August I have done NOTHING in my 3D printing hobby.

Orders languished. Many parts printed, but I found no compulsion to clean them up and assemble them. So they sat. And sat.

In fact, in that time I turned to my video gaming interest and began work on a new game in Unity.

Vijuhgames

Let’s face it. I’m a game creator. Always have been, since before I got my Commodore 64 in 1984. Hell, when I worked at Radio Shack, I started writing a TRON Light Cycles game on a TRS 80 Model III. And I wrote a Star Wars-like space shootem in BASIC on a Color Computer Model II.

My current game started out as a rolling ball Q*Bert kind of idea that I have had for more than a decade, where you roll a ball around and color squares on a grid. Evil villains would get in the way, and some would try to undo your work, and some even worse – would try to kill you.

I was in the process of this game for some time. Working on it a little bit here, a little bit there, but with no real eager effort.

Then one day I tried to implement a jump feature, where you hit a controller button and the ball would jump off the board. This would serve to avoid board elements, such as short walls or gaps.

And in doing so, I put in an Update() loop to trigger an upward impulse on the ball if you held down a joystick button.

Stupid me didn’t realize there was already a function to add a single impulse to a RigidBody, and instead put this on an Update() loop. And so when I hit the Jump button, instead of jumping once, I began to hover. All the while being able to still move around.

I had invented Space Taxi! (A Commodore 64 game I loved from my early life.)

So I began to see a new game take form instantly in my mind.

HÜVVER

Since March that’s mostly what I’ve worked on. I spent a lot of time creating a simple Taxi out of primitive shapes, and then began to work with RigidBody physics code to get the car to hover, turn, land on landing pads.

I created a city out of a single cube by scaling and populating them on the ground (on a floating cylinder world) and pretty soon I was flying around.

Then came goals, and achievements.

I soon had a pretty good-looking Taxi flying around with blue jet flames out of every attitude jet when I hovered, braked, turned, strafed. It was looking pretty good and played well.

I spent a lot of time then adding a way to make the buildings in the city take on clusters of height, so a center could be taller, outskirts, shorter, etc. And I put in 3 distinct buildings for variety.

Then I put in landing pads you had to make it to to pick up and drop off passengers. And repair/gas stations to fill up and repair damage taken from colliding with buildings.

Then I came up with the idea of achievements. After every level you got something new for the car.

Level 1: Radar so you don’t have to go searching for the next passenger pick-up point

Level 2: Radar indicator to point to the nearest repair/gas station

Level 3: Strafe control – makes landing much easier

Level 4: Turbo – jet across the city much faster

And more to come, such as larger gas tank, faster fill-ups, faster repair, auto-hover, etc. I can imagine MANY useful upgrades.

Then I put in a very rudimentary badly-implemented UI panel that simply told you what new upgrade you got. Eventually I hope to implement a choice system where you choose which upgrade you want out of a list of ones available at that level.

And the best part: It’s fun to play.

It uses an XBox 360 controller (USB) and is compiled from Unity.

At this point, I’m calling it Hüvver.

Merging Hobbies

I even used my 3D printing skills to print a model of my primitive taxi cab.

I finally got my Anycubic Photon SLA printer fixed by putting in the third screen it’s had. I got it cleaned up, put together right, and began printing again. Not a lot of prints. I find the process arduous. But the result can be amazing.

The first few prints of my Space Taxi, however, didn’t turn out well. One did, though, which I painted yellow with rattle cans and have at my desk at work.

I may begin updating this page to show my work. Concepts, what the original game was to be, what the new game is now, and what it aims to be later.

And an executable you can play.

Stay tuned.

But since then I also