Increase x to y withing w milliseconds

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Increase x to y withing w milliseconds

Post by superLED »

Just a quick question.

x = 0; y = 10;
w = 10;

I have number x, and I want x to become y withing w seconds, increasing.
That means that each second, I want x to increase with 1. But I want this function to increase x each frame.

Let's say I want an enemy to walk from the top of the screen to the bottom of the screen. And each frame, a function increases the enemy's y position, so he moves evenly from point A to point B.

I have tried to come up with a function that does this for an hour now(wow!), and I'm stuck.

I want the setup to be like this:

Code: Select all

float move(float number, float targetNumber, flaot deadLine);

if(enemy.isWalkingFromTopToBottom) {
  enemy.y += move(enemy.yPosition, enemy.targetPos, enemy.timeToBeAt_TargetPos); // Value to be changed, The number we are aiming to get to, When we want to be at 'targetPos'
}

float move(float number, float targetNumber, flaot deadLine) {
  float i = 0;  
  /*
  Calculate stuff so 'i' contains the number we should increase with in this frame
  */
  return i;
}
So, what can I put into that function?
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Increase x to y withing w milliseconds

Post by bbguimaraes »

If you are going from 0 to 10 in 5 seconds, you increase 2 each second. There are many ways to move the equation around, depending on the values you have. If you are using the standard approach of storing the position and velocity, you need to calculate the displacement from the current position to the target and set the velocity. Then you loop, increasing position according to the velocity until the target position is reached.

Just remember to decrease the time to account for the previous steps. Your functions calls should look like:

Code: Select all

move(0, 10, 5);
move(2, 10, 4);
move(4, 10, 3);
move(6, 10, 2);
move(8, 10, 1);
User avatar
Nokurn
Chaos Rift Regular
Chaos Rift Regular
Posts: 164
Joined: Mon Jan 31, 2011 12:08 pm
Favorite Gaming Platforms: PC, SNES, Dreamcast, PS2, N64
Programming Language of Choice: Proper C++
Location: Southern California
Contact:

Re: Increase x to y withing w milliseconds

Post by Nokurn »

A common approach I've seen to doing something like this (which is also the approach I use) is to have a position and a velocity (and usually an acceleration as well, for smooth movement):

Code: Select all

float x, y; // position
float vx, vy; // velocity [units / sec]
Calculate the velocity to move from <x,y> to <xf,yf> in t seconds, assuming constant velocity:

Code: Select all

void pointVelocity(float x, float y, float xf, float yf, float t, float& vx, float& vy)
{
    float dx = xf - x;
    float dy = yf - y;
    vx = dx / t;
    vy = dy / t;
}
Call an update function on every tick/frame, which increases your position by your velocity times the previous frame time:

Code: Select all

float update(float ft)
{
    if (x < xf) {
        x += vx * ft;
        if (x > xf)
            x = xf;
    }
    if (y < yf) {
        y += vy * ft;
        if (y > yf)
            y = yf;
    }
}
The part that needs explanation is the frame time (ft). This is the time that the previous frame took from start to finish, in seconds. In Allegro 5, you'd use a main loop like this:

Code: Select all

float ft = 0.0f; // first update will do nothing
while (running) {
    float t0 = (float)al_get_time();

    ALLEGRO_EVENT ev;
    while (al_get_next_event(evq, &ev))
        handleEvent(ev);
    update(ft);
    render();

    ft = (float)al_get_time() - t0;
}
You multiply your velocity [unit / sec] by time [sec] to obtain [unit], which is compatible with the units of position [unit] and can be added. This has the bonus of being frame rate independent--the technique is a form of interpolation to ensure that movement will take place at the same speed on every computer. On a slow computer with a high frame time, the object might move to the destination in the span of one frame. On a fast computer, it might take thousands of frames. But it will never arrive earlier than expected, and as long as you compensate for extremely high values of ft, it will never move farther than desired.

I don't know the exact specifics of how you want things to be set up, but you can probably make this fit if you like the idea. For milliseconds, you'd just divide the number of milliseconds by 1000 to get t.

There are other ways to achieve something similar by using absolute time offsets that are stored slightly more locally, but then you have to worry about accumulators and such. Of course, you could use an accumulator with this technique instead of multiplying by ft, but you would lose the frame rate independence.

Hope this helps.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: Increase x to y withing w milliseconds

Post by superLED »

Thanks so much for the replies! It will be really helpful.
I'll see what I can make out of this ^^
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Increase x to y withing w milliseconds

Post by XianForce »

Here's a helpful article on a reusable implementation: http://www.rivermanmedia.com/programmin ... -functions Hope that helps :)
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Increase x to y withing w milliseconds

Post by bbguimaraes »

There are some really nice concepts on that text.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: Increase x to y withing w milliseconds

Post by superLED »

I was able to find a really easy solution for this problem.

I keep track of the starting time(when the number start increasing) and the ending time(when the number is supposed to reach the goal), and the current time.
I also keep track of the starting number and the end number(what the number should become).

Then, I have startTime(100), endTime(200) and currentTime(150). I find out that currentTime is 50% between startTime and endTime.
From there, I find the number at the 50% position between startNumber(0) and endNumber(500).

Then I know that at this moment, the number should be 250.

You guys had some very interesting idea on how to do this, and how to have a more stable and powerful setup. I sure will try to implement some of that into my system!
Post Reply