1
\$\begingroup\$

I have written a game based on another game's original physics. I have all the constants the original game used in the Sega Megadrive. For example:

float ACCELERATION = 0.03287f;
float DECELERATION = 0.4f;
float FRICTION     = ACCELERATION;
float TOP_SPEED    = 8f;

when the player presses the right button I do:

     if (rightPressed) {
       speed.x += ACCELERATION * delta; // accelerate
     
       if (speed.x >= TOP_SPEED * delta) {
             speed.x = TOP_SPEED * delta; // impose a top speed limit
       }
     }
     ...
     else { // user is not moving the player (left/right)
        speed.x -= Math.min(Math.abs(speed.x), FRICTION * delta) * Math.signum(speed.x);
     }

Several lines later:

    x += speed.x * delta;
    y += speed.y * delta ;
 

Is the delta here used correctly? Should it appear anywhere as I did or just the moment I set x and y? My understanding is that speed should accelerate according to delta as well.

Another problem I have is that, by using the original game constants, the character moves in slow motion (even if I only have delta at the moment of updating x and y) so I had to multiply all constants by 15000 in order to have normal playing speed. I expected I may have to multiply by 60 (because of the 60 frames per second of Sega Megadrive) but not by 15000.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Multiplying by a time delta is a form of integration.

You do it when you want to convert a linear rate of change over time into an increment, like to go from a speed (rate of change in position over time) to a displacement (amount of change to apply this frame).

So, this is correct:

speed.x += ACCELERATION * delta; 

because we're taking a rate of change in speed over time (acceleration) and converting it to an incremental change in speed to apply this frame (a "delta v").

The same goes for these, where we convert a speed to a position increment:

x += speed.x * delta;
y += speed.y * delta ;

But this is not correct:

   if (speed.x >= TOP_SPEED * delta) {
         speed.x = TOP_SPEED * delta;

Here we're trying to compare/assign a speed to a speed. We are not integrating speed over a time interval, so it is not appropriate to multiply by delta here.

A useful trick is to use dimensional analysis. Keep track of the units on each term:

$$\require{cancel} position (m) += speed \left( \frac m s \right) \times \Delta time (s)\\ position (m) += \left( speed \times \Delta time \right) \left( \frac m {\cancel {s}} \times \cancel {s} \right)\\ position (m) += \left( speed \times \Delta time \right) (m)$$

We get the same unit (m) on both sides, and it makes sense to measure position in metres, so this little unit debugger confirms we're not doing anything too silly here.

If you repeat that with the top speed comparison above, you'll end up with m/s on the left side of the comparison (which makes sense for a speed), and just m on the right (which does not make sense for a speed!), giving you a signal that you're doing the wrong thing.

You also do not want to multiply by delta time if the change you're trying to apply is meant to be instantaneous, rather than integrated over the duration of the frame. Something like a jump or the launch of a projectile should apply an absolute change in velocity, not an acceleration over time. That way, you ensure you get consistent behaviour no matter the framerate, rather than getting short jumps when the game is running fast and long jumps when the game is chugging.

Strictly speaking, while integrating constant acceleration over time into a velocity increment is linear, and integrating constant velocity over time into a position increment is linear, integrating a constant acceleration into a changing velocity into a changing position is non-linear. Position will change quadratically. You can account for that if you want, though many games will accept this as a small integration error.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the explanation! Any ideas why the original game at 60fps (as mine) using the same constants runs fine while mine looks like slow motion? I had to multiply all constants by a factor (15000) in order to get the same result. Can't understand why is that. In my game I took all the original constants and multiplied them by 60 as I suppose the original game runs at 60 fps so their constants are intended to be at that frame rate. \$\endgroup\$ Jul 7, 2021 at 16:50
  • \$\begingroup\$ I do not have enough information about the original game and your modifications to speculate on that matter. \$\endgroup\$
    – DMGregory
    Jul 7, 2021 at 17:01

You must log in to answer this question.

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