Moving things one pixel at the time

Started by
4 comments, last by Demus79 17 years, 11 months ago
I'm crying my self to sleep every night over this. I'm currently developing a "overhead" 2d rpg in C# & Dx9. I've locked the movement and scrolling in the game with a timer. looks something like this: if(System.Environment.TickCount - lastTick >= 1) //1 as in 1 ms { updateInput(); lastTick = System.Environment.TickCount; } This works well if i move the things in the game 2 pixels at the time. But i want to move them just 1 pixel at the time to make it smoother. The thing is that i have more than 100 fps, so it should be possible to move everything 1 pixel at the time and still have normal speed. But because of the .NET timer i can't wait less than 1 ms :/ and that makes it slow. i've tested to unlock the updateInput and just have it running in the renderloop.. That works well but will run faster/slower on other computers, which ofcourse isn't good. what would you do?
Advertisement
remove the waiting and move speed*dt pixels (where dt is the timesince the last frame) rounded down, so if 0.23 seconds have passed and speed is 50pixels/second you move 11 pixels (50*0.23 = 11.5), and let 0.01 second carry over to the next frame (11/50 = 0.22)

so if frame2 runs 0.24 seconds later you'd move 50*(0.24+0.01) pixels etc.
What you need is multiply your scrolling by the time elapsed, so that slower machines (higher tick differences) will move by bigger chunks and faster machines (lower tick differences) will move by very little chunks, smootly.

Say you want to move at a constant 100 pixels / second, this means that your movement is equivalent to:

const float oneSecond = 1000.f; // since your ticks are in msconst float deltaTime = (System.Environment.TickCount - lastTick) / oneSecond;const float scrollingSpeed = 100.f;const float scrollingAmount = deltaTime * scrollingSpeed;


All your functions requiring movement, animation, etc... should always be "time based", so that it works the same on any PC.

Hope this helps
Check out System.Diagnostics.PerformanceCounter for a higher resoulution timer option.

Also, look into time based movement. This is when you pass a delta time to your update function.

Simplified to
float fdt; // delta timevoid Run(){  while(1)  {    fdt = GetElapsedTime(); // fdt in seconds    Update(fdt);    Render();  }}void Update(float dt){  // This scales k which you choose as a speed say 30 px/s (but the units are  // whatever you want them to be but relative to the rest of your world)  x = x + k*dt;  y = y + k*dt;}


The above makes sure that your units will move at the 30 px/s speed regardless of computer speed.

Cheers :)
Thank you so much! this is exactly what I was looking for.

There's been many threads about timings and how to do it in a decent way. You'll need to stop thinking in the pixel space since people may use different resolutions etc. Instead, you should think that the screen output and the game engine is separate things. What you see is only an eye blink of that particular moment inside your engine.

The idea is that your game engine works at constant speed regardless of the drawn frames. The trick is to use interpolation when rendering the frame, so that the animation will be very smooth on fast machines and a little less smoother on slower machines.

The main loop goes something like, draw the time line on the paper and you'll understand.

while(gamerunning)
{
missedframes = elapsedtime * 1/fps;

if (missedframes > 1)
{
updatelogics(missedframes);

elapsedtime -= missedframe * 1/fps;
}

render(time_in_frame);

};

This topic is closed to new replies.

Advertisement