Friday, November 4, 2016

javascript - Should game logic update per second or per frame?


I'm trying to wrap my head around how and when to update an entities position.


My game loop updates logic at 25 FPS and renders at 50-60 (Depending on the computer hardware).


So lets say I'm moving an object from 0 to 75 over a course of 100ms. In my update logic, should I update the position based on a per frame value or a per second value?


I was doing the math, and came up with and interesting find.


Since the update function updates at a rate of 25 fps, this means that it will be called at 40ms, 80ms and 120ms.


And the render function updates faster at a rate of 60 fps (for the sake of argument), which means it will be called at 16, 32, 48, 64, 80, 96, and 112ms


So if you line up all of these events on a timeline you'll notice that at the 6th render (96ms) the value of our position would be 72. And on the 7th render, the position would be 75.


Then the update function would be called at 120ms and would notice that the value is 75, but the current time is 20ms over what it should be.



Now I know that 20ms isn't much, but how do you compensate in collisions, physics, and AI for this? Should I instead update my values per frame instead of per millisecond?



Answer



I had to address this same problem, basically you're doing it the right way, updating at a set rate of updates per second, and thus a set speed per second and rendering as fast as possible independently of that speed.


That way it doesn't matter how you measure things in your update as long as you keep it consistent it'll be the same speed regardless of how fast the hardware draws things.


What you need is a way of interpolating between updates each time you do a render, since your display is updating regularly but your logic isn't.


If I may, here's some pseudo code:


For the sake of example, lets say these numbers are integers & now() returns the current time in milliseconds.


// Initial values
updatesPerSec = 25; // How many updates you do per second.
skipTicks = 1000/updatesPerSec; // The number of milliseconds between updates.

nextUpdate = now(); // When next update should occur.
currentTime = now(); // The current time.

// Game loop
while(running) {

// Update current time
currentTime = now();

// While we are behind in updates, do updates! Keep doing them till we catch up.

while(nextUpdate < currentTime) {
update();
nextUpdate += skipTicks;
}

// Calculate how far in between updates we are:
// Near 0.0 values: update just occurred.
// Near 1.0 values: update about to happen.
// Read this equation till it makes sense what's happening here:
interpolation = (currTime + skipTicks - nextUpdate) / skipTicks;

render(interpolation);
}

update() {
// update game logic & physics here
}

render(interpolation) {
// Draw objects using the interpolation value.
// Interpolate animations using this value, for eg: if you know an

// object's velocity, predict it's future position and draw the object where
// it will be in a moment's time to reduce animation 'stutter'.
}

That's actually the basic loop I use in almost anything, I can't remember where I found it but full credit to the original creator, it's served me well and keeps things incredibly simple that way.


But it does mean you need a way of actually using the interpolation value. That means for objects that are moving you need to have a sense of what direction and what speed to interpolate the value. With updates of velocity 25 times a second, the simple interpolation will achieve the appearance of logic updates every frame without actually calculating them.


Hopefully that helps!


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...