0
\$\begingroup\$

I've search a bit and tried to find a decent answer to this but have failed majorly. Basically I'm trying to loop an AI object between two points. Heres some of the code I have so far:

class Object
{
    Vector3 startPos;
    Vector3 endPos;

    Vector3 curPos;
    Vector3 curVel; 
};

struct Vector3
{
    float x;
    float y;
    float z;
}


Start()
{
    startPos = Vector3( 1, 0, 0 );
    endPos = Vector3( -1, 0, 0 );
    curPos = Vector3( 0, 0, 0 )

    Generate();
}

Generate()
{
    // Standard code to generate angular velocity
    // Calculate angle between two points
    // Calculate velocity based on angle
}

Update()
{
    // Add velocity
    curPos += curVel;

    // If the position has reached the end point
    if( curPos == endPos )
    {
        // Reverse movement positions
        Vector3 temp = endPos;
        startPos = endPos;
        endPos = temp;

        // Recalculate velocity
        Generate();
    }
}

I'm now stuck, as you can see from the comments, the velocity could take the position of the object to something like (-1.5, 0, 0) which would mean the if statement wouldn't work. For the initial movement, it could be fixed using

if( curPos <= endPos )
{
    // Reverse
}

However, when I then reverse the positions, problems arise and it won't work. Any ideas?

\$\endgroup\$
1
\$\begingroup\$

One approach is to use distance as it will always be a positive number so you don't need to account for sign.

When at startPos, compute the distance from startPos to endPos and store this is a float called distanceToTravel (or similar). Each tick of Update() compute the distance traveled so far (this is startPos to currPos), call this distanceTraveledSoFar (or similar). Then compare distanceTraveledSoFar to distanceToTravel:

if (distanceTraveledSoFar >= distanceToTravel)
{
    // You've arrived!
}

A potential optimization is to use distance squared values rather than distance as sqrt is relatively costly to call each tick.

\$\endgroup\$
  • \$\begingroup\$ Excellent! Using distance hadn't crossed my mind, silly me! Thanks! \$\endgroup\$ – user2990037 May 5 '14 at 21:28
0
\$\begingroup\$

Define a function that takes care of not overshooting the target, like this:

template<typename T, typename D>
T Approach(T from, T to, D limit)
{
    D diff = Abs(from - to);
    limit = Abs(limit);
    if(diff > limit)
    {
        if(from < to)
            return from + limit;
        else
            return from - limit;
    }
    else
        return to;
};

Now replace this

curPos += curVel;

with

curPos = Approach(curPos, endPos, curVel);

And you can just check for equality.

Edit:
Above works well if the movement is limited and straight forward. But movement is often not that predictable. The alternative is checking for proximity rather than the exact position. This will become necessary if the movement is physics based.

// If the position is very near the end point
if((endPos-curPos).length() < 25)
{
    // Reverse movement positions
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.