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.
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.