There are a dozen ways I could word this question, but to keep my thoughts in line, I'm phrasing it in line with my problem at hand.

So I'm creating a floating platform that I would like to be able to simply travel from one designated point to another, and then return back to the first, and just pass between the two in a straight line. However, just to make it a little more interesting, I want to add a few rules to the platform.

  1. I'm coding it to travel multiples of whole tile values of world data. So if the platform is not stationary, then it will travel at least one whole tile width or tile height.
  2. Within one tile length, I would like it to accelerate from a stop to a given max speed.
  3. Upon reaching one tile length's distance, I would like it to slow to a stop at given tile coordinate and then repeat the process in reverse.

enter image description here

The first two parts aren't too difficult, essentially I'm having trouble with the third part. I would like the platform to stop exactly at a tile coordinate, but being as I'm working with acceleration, it would seem easy to simply begin applying acceleration in the opposite direction to a value storing the platform's current speed once it reaches one tile's length of distance (assuming that the tile is traveling more than one tile-length, but to keep things simple, let's just assume it is)- but then the question is what would the correct value be for acceleration to increment from to produce this effect? How would I find that value?

  • 1
    \$\begingroup\$ I don't have time for a full answer at the moment, but take a look at this: red3d.com/cwr/steer/gdc99, specifically the "Arrival" section. Mimic that behavior to slow to a stop and reverse it to speed up from a stop. \$\endgroup\$
    – MichaelHouse
    Oct 2 '12 at 0:47
  • \$\begingroup\$ Bookmarked. That is a wealth of valuable information you have just enlightened me to, Sir. \$\endgroup\$ Oct 2 '12 at 1:00
  • \$\begingroup\$ This "desired_velocity = (clipped_speed / distance) * target_offset" sort of makes sense, but not exactly. Once I find desired_velocity, to I subtract it from the object's current speed? \$\endgroup\$ Oct 2 '12 at 1:59
  • \$\begingroup\$ I use it to update the acceleration value: acceleration = desired_velocity - currentVelocity Then apply that acceleration as you normally would. I'll create an answer in a bit further showing what I do. \$\endgroup\$
    – MichaelHouse
    Oct 2 '12 at 2:11

Using these steering behaviors as a guide. Looking at the arrive behavior:

enter image description here

Arrival behavior is identical to seek while the character is far from its target. But instead of moving through the target at full speed, this behavior causes the character to slow down as it approaches the target, eventually slowing to a stop coincident with the target.

We can create an "arrive at" function like something similar to this:

arriveAtPoint(Vector2f position, Vector2f target) {
    float slowing_distance = 1;
    Vector2f target_offset = target - position;
    float distance = target_offset.length();
    float ramped_speed = currentVelocity * (distance / slowing_distance);
    float clipped_speed = Math.min(ramped_speed, currentVelocity);
    targetLinearVelocity = target_offset.scale(clipped_speed / distance);
    acceleration = targetLinearVelocity -linearVelocity;

This will update the acceleration we need to use to apply to the object in motion.

  • \$\begingroup\$ And just for clarification, linearVelocity would be the velocity at which our object would have been currently traveling after the prior update? \$\endgroup\$ Oct 2 '12 at 3:48
  • \$\begingroup\$ Your phrasing is pretty strange. But, linearVelocity == currentVelocity. \$\endgroup\$
    – MichaelHouse
    Oct 2 '12 at 3:53
  • 3
    \$\begingroup\$ I disagree with this approach on the basis that it is over-complicated. It's possible to do this with a simple tween using equations of motion (the SUVAT formulas). A little algebra and you can calculate the inputs required to hit a desired target precisely. \$\endgroup\$ Oct 2 '12 at 7:03
  • 1
    \$\begingroup\$ It would be helpful if you could elaborate that with an answer? \$\endgroup\$ Oct 2 '12 at 19:05
  • \$\begingroup\$ @AndrewRussell I'd like to see that answer too. \$\endgroup\$
    – MichaelHouse
    Oct 2 '12 at 20:26

Take a look at this page: http://sol.gfxile.net/interpolation/index.html

It seems that you want a effect just like the smoothstep:

smoothstep graphic

If you have leftmost point, the rightmost point the platform should achieve, and the time it should use to go make a full sequence, something like this may be ok:

foreach frame:

float smoothstep(float t, int level = 1)
    float ret = t;
    for(int i = 0; i < level; ++i)
        ret = pow(ret, 2) * (3 - 2 * ret);
    return ret;

currentTime += deltaTime;
if(currentTime > fullTime) currentTime -= fullTime;
float halfTime = fullTime / 2.0;
float t = abs(currentTime - halfTime) / halfTime;
t = smoothstep(t, 1);
platformPosition = rightPoint * t + leftPoint * (1 - t);

if you're using a physics engine, you can make it with impulses, shouldn't be that hard to translate. If you want a even smoother process, you can increase the smoothstep level. Multiple smoothstep


You can use XnaTweener that provides easing functions that interpolate values from one point to another in a easy way...

Here is a reply with some code based in the Xna Tweener project and a video showing how it performs...



You should have a sequence of keys that defines the platform movement, like this:

public class MovementKey
    public float Time = 0;
    public float Duration;
    public Vector2 Traslation;            // Traslation is relative to previous key
    public TweeningFunction Function;

    internal float GetRatio( float Elapsed )   
        // Always return a value in [0..1] range
        //    0 .. Start position relative to accumulated traslations of previous keys
        //    1 .. Target relative position reached.. then should go to next key if avalaible
        return Function( Elapsed, 0, 1, Duration ); 

And then you can handle the movement this way:

public class Movement {

    List<MovementKey> Keys;

    public void Update( float Seconds)

        float ratio;
        if (Playing) Elapsed += Seconds;

        while ( index!= Keys.Count - 1 && Elapsed > Keys[iKey + 1].Time )
            Traslation += Keys[iKey].Traslation;  // Relative

       if ( index == Keys.Count - 1 && Elapsed > Keys[iKey].Time + Keys[iKey].Duration )
          ratio = 1;
          if ( DoLoop )
              Elapsed -= (Keys[index].Time + Keys[iKey].Duration);
              Index = 0;
              Traslation = Vector2.zero;
       else {                    
           ratio = Keys[index].GetRatio( Elapsed - Keys[index].Time );

       Position = DefaultPosition + Traslation + ratio * Keys[index].Traslation;        

"DefaultPosition" is the start position, "Traslation" accumulates movement of several keys, and each key traslation is relative to the previous key, so when you multiply it by a ratio factor [0..1] it returns the interpolated relative traslation walked to reach that key from the previous key...

Here you have another video that shows a platform movement defined as described here...


I have redone this code trying to make it easy to understand... maybe it has some bug... the original code handle several instance of the same movement but with some delays among each instance... I'm sure this code can be redesigned to be easier...

  • \$\begingroup\$ Thank you, this is helpful, although it's being used in what seems like the context of an animation, I'm trying to translate it in my head to what would be more contextual to my situation at hand. \$\endgroup\$ Oct 2 '12 at 19:10
  • \$\begingroup\$ I'm lost. I can't figure out how to relate this to my current situation at all. o.o;; \$\endgroup\$ Oct 2 '12 at 20:55
  • \$\begingroup\$ You have an animation... you are trying to animate in position terms... \$\endgroup\$
    – Blau
    Oct 2 '12 at 21:32
  • \$\begingroup\$ Forgive me, the reason why I'm having difficulty, is because I'm trying to bootstrap this idea and translate it into a system that works on a speed=velocity*time system, whereas this system simply nudges the location of the object procedurally (nothing wrong with that, just hard to find the proper way to relate the two). \$\endgroup\$ Oct 2 '12 at 23:03

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.