Advertisement

Basic steering behaviour

Started by November 28, 2011 09:00 PM
2 comments, last by BeautifulAlgorithms 12 years, 11 months ago
I'm trying to implement simple (at the moment) steering behaviour for a course at uni. I've got seek working but it always misses the target by a small amount, sort of going into orbit instead of passing directly through the target. Even if it has plenty of run-up to the target, it might still miss it by a few pixels and begin orbiting. I think I know why this is, but I don't know what to do to solve it. Arrival behaviour is worse because it takes forever to 'arrive' because it keep orbiting. In the implementation here, the steering vector sort of waves back and forth, which mine doesn't. Here's the code:



float maxForce = MAX_FORCE;
sf::Vector2f vel = m_Velocity;
sf::Vector2f pos = m_Position;
sf::Vector2f steer; // The steering vector.
sf::Vector2f des = target - pos; // A vector pointing from the location to the target.
float d = sfm::Length(des); // Distance from the target is the magnitude of the vector.
if (d > 0) {
sfm::Normalize(des);
des *= MAX_SPEED;
steer = des - vel;
// Limit to maximum steering force
float steerLength = sfm::Length(steer);
if (steerLength > maxForce)
{
steer *= maxForce/steerLength;
}
} else {
steer = sf::Vector2f(0.0f, 0.0f);
}
m_Acceleration = steer;



Then every frame the position as calculated as such:



m_Velocity += m_Acceleration*m_FrameTime;
if (sfm::Length(m_Velocity) > MAX_SPEED)
{
sfm::Normalize(m_Velocity);
m_Velocity *= MAX_SPEED;
}
m_Position += m_Velocity*m_FrameTime;
m_Acceleration = sf::Vector2f(0.0f, 0.0f);



Any help would be appreciated thanks!
Euler integration isn't exact, and neither are floating point numbers. Your distance is never going to be exactly 0. Instead of checking whether d > 0, check whether it's greater than some other minimum distance (the radius of your object is usually a good start).

EDIT: Also consider that you are normalizing des and then multiplying by MAX_SPEED. So if you're less than 1 frame away from your destination, you'll overshoot.
Anthony Umfer
Advertisement

Euler integration isn't exact, and neither are floating point numbers. Your distance is never going to be exactly 0. Instead of checking whether d > 0, check whether it's greater than some other minimum distance (the radius of your object is usually a good start).

EDIT: Also consider that you are normalizing des and then multiplying by MAX_SPEED. So if you're less than 1 frame away from your destination, you'll overshoot.

Ignore the d > 0 part, it's copied from some other code and doesn't affect the functionality. The code I posted was for seek (sorry if that wasn't clear), and my boid misses it's target by a lot more than a float error. I might try and get a video up to show what I mean.

EDIT: I've actually got arrive working well now, slowing it down gives it time to adjust it's velocity, but seek is still a problem. If the boid is on any kind of angle when approaching the target, it will pass off to the side.
It's a while since I played around with steering behaviours but what you have looks correct to me, hence I'm wondering if there isn't a small bug somewhere in the rest of your code. I recommend you simply output all variables and values to a debug window and check the answers by hand. Doing so is a tedious and annoying but you will (usually!) find the problem quickly.

I assume you've already got your hands on Mat Buckland's Programming AI by Example? If not then pick this up as steering behaviours are explained extremely well in there.

This topic is closed to new replies.

Advertisement