Jump to content
  • Advertisement
Sign in to follow this  
unsigned short

Sample source for the leader follow steering behavior

This topic is 3869 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I'm looking for some sample source code for the leader follow steering behavior. I already googled but didn't find anything. The applets on red3d.com don't have source code included. I theoretically know how the behavior works (combination of separation and arrival) but I my implementation doesn't work properly. Hope someone can help :)

Share this post


Link to post
Share on other sites
Advertisement
If you're happy to post your implementation (jut the relevant parts) we can take a look at it and try and work out why it isn't working.

Share this post


Link to post
Share on other sites
Ok I think that might be the best solution. I wrote an extra program using SDL to test out the steering stuff, so it's quite easy to post some code.

Here's the relevant code:

Vector2 truncateVector2(const Vector2 &vec,float maxLen) {
/*if (vec.lengthSq()>maxLen) {
return vec.normalizedCopy()*maxLen;
}*/

return vec;
}

class Unit {
private:
Vector2 m_pos;
Vector2 m_vel;
Vector2 m_targetPos;

static const float maxSpeed;
static const float maxForce;
static const float arrivalSlowingDistance;
static const float radius;

public:
Unit(const Vector2 &pos):m_pos(pos),m_targetPos(pos) {}

const Vector2 &getPosition() const { return m_pos; }

void update(float secsPerFrame,const std::vector<Unit> &otherUnits);

void addCommand(const Vector2 &targetPos);
void addForce(const Vector2 &force);
Vector2 computeArrivalSteeringForce(const Vector2 &targetPos) const;
Vector2 computeSeparationSteeringForce(const std::vector<Unit> &otherUnits) const;
};

const float Unit::maxSpeed = 100.0f;
const float Unit::maxForce = 100.0f;
const float Unit::arrivalSlowingDistance = 100.0f;
const float Unit::radius = 40.0f;

void Unit::update(float secsPerFrame,const std::vector<Unit> &otherUnits) {
Vector2 force = computeSeparationSteeringForce(otherUnits)*2.0f;
force += computeArrivalSteeringForce(m_targetPos)*1.0f;

addForce(force);

m_pos += m_vel*secsPerFrame;
}

void Unit::addCommand(const Vector2 &targetPos) {
m_targetPos=targetPos;
}

void Unit::addForce(const Vector2 &force) {
m_vel += truncateVector2(force,maxForce);
m_vel = truncateVector2(m_vel,maxSpeed);
}

Vector2 Unit::computeArrivalSteeringForce(const Vector2 &targetPos) const {
Vector2 target_offset = targetPos - getPosition();
if (target_offset == Vector2::ZERO) {
return Vector2::ZERO;
}
float distance = target_offset.length();

float ramped_speed = maxSpeed * (distance / arrivalSlowingDistance);
float clipped_speed = std::min(ramped_speed, maxSpeed);
Vector2 desired_velocity = (clipped_speed / distance) * target_offset;
return desired_velocity - m_vel;
}

Vector2 Unit::computeSeparationSteeringForce(const std::vector<Unit> &otherUnits) const {
Vector2 desired_velocity;
for (std::vector<Unit>::const_iterator unitIter=otherUnits.begin(); unitIter!=otherUnits.end(); ++unitIter) {
Vector2 diff=getPosition()-unitIter->getPosition();
float lenSq=diff.lengthSq();
if (lenSq<radius*radius) {

//diff.normalize();
//diff *= 1.0f/lenSq;
desired_velocity += diff;//-m_vel;
}
}

return desired_velocity;// - m_vel;
}

std::vector<Unit> g_units;

void move(float secsPerFrame) {
for (std::vector<Unit>::iterator unitIter=g_units.begin(); unitIter!=g_units.end(); ++unitIter) {
unitIter->update(secsPerFrame,g_units);
}
}

void addCommand() {
int x,y;
SDL_GetMouseState(&x,&y);

for (std::vector<Unit>::iterator unitIter=g_units.begin(); unitIter!=g_units.end(); ++unitIter) {
unitIter->addCommand(Vector2(x,y));
}
}





the addCommand function is called each time the mouse is moved and just updates the target position. move is called each frame. Note: the units actually don't follow a leader but just the mouse cursor. But that shouldn't be a problem, right? The problem is that the units are jittering around while moving, the motion is not as smooth as in the applets on steeringbehaviors.de

Hope someone can help :)

(hmm the cpp tag doesn't work?)

Edited by moderator to fix 'source' tags

[Edited by - Timkin on February 17, 2008 8:03:58 PM]

Share this post


Link to post
Share on other sites
(use the 'source' and '/source' tags for code...remove the quotes and replace with square brackets)

I've only taken a quick pass over your code as I'm a bit swamped at the moment... but as I see it the following is a problem


void Unit::addForce(const Vector2 &force) {
m_vel += truncateVector2(force,maxForce);
m_vel = truncateVector2(m_vel,maxSpeed);
}


Simple kinematics tells us that v = u + at and a = F/m. So, your code should be

m_vel += truncateVector2(force,maxForce)*secsPerFrame;

and then truncate it as needed. Of your object does not have unit mass then it should be force/mass in the above equation.

I'll try and find time to look further into your code later today or tonight.

Cheers,

Timkin

Share this post


Link to post
Share on other sites
Thanks very much for your answer!
I tried out your suggestion, however when changing
m_vel += truncateVector2(force,maxForce);

to
m_vel += truncateVector2(force,maxForce)*secsPerFrame;


the units move very slowly because here
m_pos += m_vel*secsPerFrame;


I already multiply with secsPerFrame.

If it helps I can also post the complete code (only uses SDL) to make it easier to test ...

Share this post


Link to post
Share on other sites
That's not an error... it's just the approximation scheme you're using.

Here is my advised scheme (again I'm assuming a unit mass particle)

Inputs:

x(t): position at time t
v(t): velocity at time t
f(t): net force at time t
Δt: time step

Outputs:
x(t+Δt): position at time t+Δt
v(t+Δt): velocity at time t+Δt


x(t+Δt) = x(t) + v(t)Δt + 1/2f(t)Δt2
v(t+Δt) = v(t) + f(t)Δt

This is equivalent to writing
v(t+Δt) = v(t) + f(t)Δt
x(t+Δt) = x(t) + (v(t) + v(t+Δt))Δt/2

which uses a first order approximation scheme


If you find that your particles are moving too slowly, then you need to simply increase the forces applied on them per unit time... or decrease their mass.

Cheers,

Timkin

Share this post


Link to post
Share on other sites
Thanks for your answer. I tried out your solution, but now it doesn't work at all. Perhaps I'm doing something wrong ...

I think the best is to post the complete code. You only need SDL to compile. The unit.bmp is a simple 32x32 circle image.

Here it is!

[Edited by - unsigned short on February 19, 2008 2:58:13 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!