1
\$\begingroup\$

I'm trying to learn how to adapt my old values to new values. First of all, I don't use delta time at all. My game has lock with 30 FPS and I want to lock it with 60 FPS, I wrote all my values in pixels per frame. I can't just multiply by 0.5 ratio when it's not a linear equation. For example:

// INIT

speed = 10;
gravity = 1;
position = 0;

// UPDATE

speed += gravity;
position += speed;

When I reach frame 30 with 30 FPS lock, speed is equal to 40 and position is equal to 765. If I lock to 60 FPS, I want to get half of speed and position on frame 30 and same values on frame 60.

I have seen many topics about this problem, but still can't figure out how to just adapt these values a single time for new FPS lock to have the same behavior as before.

Generally, I want to learn how to read these equations to come up with formulas inside them to build graphs or something (I mean, when people show formulas from Wolfram, they somehow break down equations and read them as formulas).

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

First, we know that if we halve the timestep, we have to halve the gravity, so that we still add the same total amount to the speed when we run twice as many iterations.

Adjusting the initial speed or velocity is a little more nuanced. The equation for continuous motion under constant acceleration is:

$$\vec p (t) = \vec p_0 + t \vec v_0 + t^2 \frac {\vec a} 2$$

But using an Euler integrator like in your code is a discrete approximation of this that adds some integration error — so your object won't trace exactly the same parabola as the continuous physics would suggest.

It turns out that this integration error is exactly equivalent to shifting the initial velocity by one half a timestep. It's like, anytime you read/write the velocity in the Euler simulation, you're actually looking at the object slightly in the past, compared to its position.

So, we can convert between these modes just by adding/subtracting one half a time step's worth of acceleration. If we have two objects following exactly the same parabola of positions over time, one moving continuously with initial velocity \$\vec v_\infty\$ and one moving discretely at some fixed fps with initial velocity \$\vec v_{fps}\$, that looks like this:

$$\vec v_\infty = v_{fps} + \vec a \frac 1 {fps \cdot 2}\\ \vec v_{fps} = v_\infty - \vec a \frac 1 {fps \cdot 2}$$

So to get from your 30 fps initial velocity to 60, we first add half a 30 fps step of gravity to get to the velocity for the continuous sim, then subtract half a 60 fps step of gravity to get the initial velocity for the 60 fps sim:

$$\begin{align} v_{60} &= v_\inf - \frac {g_{60}} 2\\ &= v_{30} + \frac {g_{30}} 2 - \frac {g_{30}} 4\\ &= v_{30} + \frac {g_{30}} 4\\ &= 1 + \frac {10} 4\\ &= 1 + 2.5\\ &= 3.5 \end{align}$$

So your new initial velocity for this object is 3.5 instead of 1. Adding half this velocity to your position each frame will exactly reproduce the positions seen in your 30 fps sim, just two ticks apart. (We add half because we haven't changed the units — we're still measuring speed in "pixels per thirtieth of a second" to keep it directly comparable for any calculations you have that are checking it against threshold speeds)

Here's a spreadsheet proving these match as desired - you can click in the cells to see the exact calculations I'm doing at each step:

Table of speeds and positions over time at 30 and 60 FPS

There is a wrinkle though: the speed you get after some even number of ticks won't exactly match the speed you had at half that many ticks in the 30 fps case. That's again due to this time-shifting. Where the 30 fps sim was giving us speeds measured at \$t - \frac 1 {60}\$ in the continuous world, our 60 fps sim is telling us what the speed was at \$t - \frac 1 {120}\$. So you need to subtract half a (60 fps) timestep's acceleration from the speed to see the same value you got from the 30 fps sim at the corresponding tick.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .