Monday, October 29, 2012

How to Make a Basic AI - Seek & Wander


If anyone remembers in Super Mario 64, the goombas were different then their 2D counter parts. Instead of simply walking in a straight line, they actually did some somewhat more dynamic AI. They walked around and when you got close, they suddenly turned toward you and ran at you. This is a very basic AI that can work in a 3D game and today I'd like to show how it can be done.

First off let's break down what kind of behaviours the goomba is using. It uses two simple AI behaviours...

  • Seek
  • Wander
The seek behaviour means to head towards a designated target, simple enough. The behaviour is a little more complicated but it eventually involves the same thing. It seeks towards a target, but what it does is calculate a new target in front of itself whenever it's called to make it appear like its just walking around aimlessly.

Physics System


So we know what these behaviours are and they sound pretty simple. Before you just go ahead and make them we need to make sure we have a physics system of some sort. So let's say we have our "Goomba object", well if we want to accurately calculate forces for our AI, we need to make sure he adheres to some form of physics.  This physics system is not too complicated, in fact all it needs to consist of for us at this point is the following...

  • Force
  • Mass
  • Acceleration
  • Velocity (Speed)
  • Position
You would give your goomba this physics system and give it an update function that applies these forces every frame. With the proper system, simply applying some force, will automatically do all the calculations to make the goomba move. So Force = Mass*acceleration, velocity += acceleration, position += velocity or something of the sort. So this means in our AI behaviours we would be calculating the forced required to go to our target.


Calculating the target


For our Goomba, we would first of all need to keep track of it's target. A vector represents a point in space, X,Y,Z which is what our game world consists of. In this case our target would be our player, so when we call the function "SetTarget", you would pass in Mario, the player's position (as a Vector XYZ) into the function. Great, we have our target now.

Now we have our target (MARIO) and our goomba's position so how do we make the goomba go towards Mario? Well the benefit of using vectors is that when you subtract one vector from another, it creates whats called a "direction vector". It's essentially a direction pointing from one vector to another, which is exactly where want to make our goomba go. This direction is exactly where we would apply our force towards!



So to find our direction vector it would be MARIO's position - GOOMBA's position. We would make sure to normalize (magnitude is 1) this direction vector and multiply it by the amount of force units we actually want to apply. We then return this force we have calculated to our Goomba's physics update to apply this force. The force would be calculated and sent to accel, then velocity and calculating our position.



This essentially how we seek towards an object! This can be turned into a "flee" behaviour where our goomba will run away instead by simply having the force calculated be the negative value instead. "-Force".

Wandering


Wandering on the other hand is more complicated but still applies the same concept of targetting. Instead of taking Mario as a target, we generate one ourselves. 

What our goomba does is he generates a vector directly in front of the direction he is already facing. From there we pass our goomba some angle which we will randomize to be either negative or positive. The purpose of this is to generate a random direction for our goomba to go (i.e. veer left of veer right). From there the vector we generated earlier will be rotated by the angle.



From there it's simply calculating the direction vector from our target to our goomba. The same process as seek now.

Combining them


Well obviously it seems like trying to use both of them at once might not work so it's simply a matter of checking for Mario's position. So we would want our Goomba to wander around when Mario is far away and chase him when he gets close. 

So we set some radius for the goomba. This radius will calculate whether Mario's position (using the same direction vector calculation) is within the radius. If it's Mario isn't within our radius thing, let the goomba just wander around, he doesn't care or even know Mario is near yet. If Mario gets inside the circle our Goomba is suddenly alert, he knows Mario is near. He should go and get him, therefore applying the seek behaviour.

 

Depending on how you do it, if you have both behaviours activated at once, you will want to disable the other one so that you don't get both forces influencing the Goomba.

And that's pretty much the basics for a simple AI system. You don't necesarily need the physics system noted earlier but it will help greatly for calculations and it's highly advised. It's not all too hard to do but the harder stuff will come later when you need group behaviours such as birds flocking together. That's a topic for another blog post though.


1 comment: