Welcome back.
If you made it through the previous video, oh, mwah.
Thank you so much.
In this one, I'm just going to get right down
into writing the code.
What am I talking about?
"Steering Behaviors for Autonomous Characters."
All of the examples I'm going to code and show you
are based on the 1999 paper by Craig Reynolds.
I talk a lot more about that in the previous video.
You could go back and watch that.
Here, I need to start somewhere.
And the canonical example to demonstrate a steering force
is the steering behavior seek or pursuit of a static target.
Now, I'm about to go diagram this myself,
but I just want to point something out here.
Steering equals desired velocity minus velocity.
That's all there is to it.
It's a very simple formula.
Now, what the desired velocity actually is--
that's the tricky question.
The good news for seek--
it's pretty easy to come up with the desired velocity.
But as we get to more and more examples,
and as you make your own behaviors,
thinking about what is the objects, the entities,
the creature, the particle, the vehicle's desire
is incredibly important.
So let's map out a scenario in p5.js.
So what do I have?
I have a vehicle that's my particle or mover
object essentially.
I'm going to draw it as a triangle.
It's got a current velocity.
And then I've also got a target.
So the first question that needs to be asked
is, what is the desired velocity?
Going back to Reynolds' paper, this is where we are.
We're on the action selection step.
What are the goals for this particular vehicle?
Maybe it's hungry.
This is food.
And its goal is to get there to eat the food.
Now, you might have your own interpretation
of this scenario, but I'm going to put this out there.
I think that the vehicle's desired velocity
is to move as fast as it possibly can directly
towards the target.
For example, if it could have this velocity,
if that were its velocity vector,
it would instantly teleport to the target.
But we have to remember that this is
a world that we're designing.
And we need to put some constraints on it.
Returning back to the simple vehicle model in the paper,
you'll notice there's a property there called max_speed.
This is not something that I have necessarily introduced
in previous examples.
The vehicle, in addition to having a position, a velocity,
an acceleration, all those types of things,
now has a maximum speed.
And I'm going to define then its desired velocity
as a vector that points directly to the target
with a length of maximum speed.
Step two-- steering.
And that is that wonderful, beautiful, simple formula.
The steering force is the desired velocity
minus its current velocity.
Think about this for a moment.
It actually makes total sense, right?
If I'm going in this direction, but I
want to be going in this direction,
the way I should steer is the difference
between those two things.
It's like almost an error.
If I'm moving in exactly the same direction as my desired
velocity, the difference between all those things is zero.
I don't need to change my velocity.
Now, you might be thinking, didn't we do this already?
Isn't this just gravitational attraction?
Like this particle is attracted to this attractor?
Well, it's very similar, but it's quite different.
In the gravitational attraction example,
the particle body had no ability to perceive its environment.
It didn't understand if I'm going in this direction,
maybe I need to compensate for that to get to the target
more quickly.
It was just being pulled.
So the force being applied was just
a force that points directly from the object
to the target in the gravitational attraction
example.
Let's now look at if I were to actually work out desired minus
velocity, what would I see?
This is that desired vector.
If I take the velocity vector, if I
were to add desired plus velocity,
I would put the velocity here.
But to subtract desired minus velocity,
I just take the velocity, turn it around,
and now I have this vector.
This is my steering force.
If I take this and kind of put it up here,
you could see how there's an intelligence to pushing
this vehicle further in the direction of the target itself
based on the fact that it's moving in this direction.
If you want, pause the video.
Have this vehicle moving in this direction,
and then work out what's the steering force.
You'll see that it's different.
And here this autonomous agent is perceiving its environment
by understanding where the target is and its own velocity
and how that plays a role into what force it could use
to steer towards that target.
And this is it.
We're ready to go to the code because all I need to do
is figure out, how do I calculate this desired
velocity?
Then do the vector math to get the steering force, and then
what?
Apply force.
Everything else is just all the same stuff
that I've done in previous videos.
Step three-- locomotion.
Apply force.
Force goes into acceleration.
Acceleration goes into velocity.
Velocity goes into the position.
All that stuff is all stuff that I've done before.
I'm going to begin with the particle class from chapter 4
and just change that particle to now be called a vehicle.
I'm going to just give it an empty velocity to start with.
It doesn't need the lifetime variable anymore.
I mean, I might want that someday,
but I'm going to remove that.
And I want to add an additional function.
I want to add a function called seek
that presumably will receive a vector, which is the target.
Calculate the steering force within that function.
But before I write the code in there,
let's go to Setup and Draw and create a vehicle.
There we go.
Now, my vehicle is a tiny, little dot.
Let's change that into a triangle
so I can see it point in the direction that it's moving.
There's my little triangle.
Let's make that quite a bit bigger.
And there we go.
Now I need a target.
I'll make a vector to define the position of the target
at the mouse location, and then just draw a circle there.
And, certainly, the target could be something
more sophisticated, but I think this is a quick way for me
to demonstrate the idea.
Vehicle.seek(target).
Step one-- what is the desired velocity of vector that
points from the vehicle's position
to the target with a length of magnitude of maximum speed?
Using vector subtraction, I now have a vector
called desired that points all the way from the position
to the target.
I need to set its magnitude to maximum speed.
Oh, I don't have a maximum speed variable.
So now I need to make one up.
I'm going to just pick four.
This is obviously a major parameter
that will really affect the way your system behaves.
And it might be something that you make different vehicles
with different maximum speeds or initialize them
based on some algorithm, but I'm just
going to hard code the number in four right there.
Next step-- the steering force is the desired
velocity minus the actual velocity,
the current velocity itself.
Take that desired velocity.
Subtract the velocity.
And we now have it in a force vector called steering.
Applied force-- oh, we're going to be going so fast.
Well, look at that.
It's seeking the target.
I should probably rotate it according to its velocity.
Remember in chapter 3, I show that you
could call the heading function to get the angle associated
with that velocity vector and then rotate by that angle.
And look at that.
Look how perfectly it steers towards that target,
almost too perfectly.
What am I missing?
Well, in a way, I'm not missing anything.
This example is complete.
This is the algorithm for calculating a steering
force based on a desired velocity for seeking a target.
But going back to Reynolds' paper,
it's important to remember that, what is the goal here?
The goal isn't necessarily for the vehicle
to reach the target as fast as possible.
I mean, it might be.
But if that's really the case, we
have the power to just set its location
to the target's location.
The goal is to simulate motion behaviors
in a lifelike and improvisational manner.
And the way that we can really tune our system now
is not just based on that maximum speed.
There's another property here-- maximum force.
What is this vehicle's ability to steer?
Is it able to turn on a dime and instantly get to that target?
Or does it take a lot of work for it to change its direction
and speed up and slow down?
I'm going to add a maximum force property
and set it to something quite low.
The idea is that this maximum force property
is something that limits the magnitude of that steering
force.
If the steering force magnitude is
less than that maximum force, it doesn't need
to make it that maximum force.
That's just a maximum.
So rather than setting the magnitude directly
like I did with desired, I want to use the limit function.
Now let's run this sketch again.
Now, it's moving really slowly.
Because, remember, steering isn't just changing direction.
It's any kind of change in the velocity vector.
So it starts with a velocity vector of zero.
It takes a while for it to ramp up and get some speed.
But we can quickly see now if I were
to change the maximum force from 0.01 to 1,
now we're back in that turning on a dime.
What happens if I make the maximum speed even higher?
Now you could see it's able to steer quite effectively
but also go much faster.
So those properties play a huge role
in the behavior of the agent in the system.
Before I move on, I want to make one organizational change here.
I actually don't need separate desired velocity and steering
force vectors.
Ultimately, I don't need to save that desired velocity
its own variable.
So I'm actually just going to change this to be called force,
set its magnitude to maximum speed,
and then just say force subtract this dot velocity.
Rather than create a new vector that
is the result of desired minus velocity,
I could just calculate the desired
and then subtract the velocity out of it
and call it force the whole way through.
I've got a lot more things to demonstrate.
Namely, I want to change this into an arrive behavior.
So right now, you see that the vehicle
is shooting past the target and has to turn back around.
How could it have as a goal to slow down and stop
when it reaches the target?
Maybe you want to try that on your own.
Stop.
I'm about to say goodbye, and I'll let it say goodbye.
But before I say goodbye, since I have this maximum speed
variable, I'm really using it in this video
to demonstrate the idea of setting the magnitude
of the desired velocity.
But if that's the vehicle's maximum speed,
I should also limit its actual velocity by that.
Ultimately, I'm not sure how much difference that's
going to make in the actual end result,
but it is an important note for me to add that property in here
as well.
OK, back to me saying goodbye.
But here's two exercises that you
could try if you're looking for something to expand on this.
One is, what happens if you attach sliders to maximum speed
and maximum force?
How does that affect the behavior
of the vehicle in real time as you're
tweaking those parameters?
Also, Reynolds describes in his paper
a behavior known as pursuit.
So what if the target is moving?
On the one hand, it could be exactly the same algorithm
that you just seek wherever the current location of the target
is.
That's ultimately what's happening here
as I move it with the mouse.
But if the vehicle is able to perceive its environment
and see which direction the target is moving,
couldn't it make a prediction as to where
it's going to be a little bit in the future
and seek that location rather than
the exact position of the target itself right at this moment?
So that's another thing you could try.
Take a look at how this is explained
in Reynolds' paper, which I've linked
to in the video description.
All right.
Next up, the arrive force and then more and more and more.
I don't know how many of these I'm going to do.
But, eventually, I'll get to--
I would love to get to all of them in future videos.
Thanks for sticking with me.
We'll look forward to hearing what you think
and what questions you have in the comments.
And I will see you in the next video.
[MUSIC PLAYING]