1

I've inherited a code base in which everything is coded to run at 30 FPS and uses integers.

I would like to upgrade the frame rate to 60 FPS, naturally I thought about using floats but it ain't that easy to do so. I created a git branch and tried to port what appeared to made sense to use float but it ended up catastrophic, things would fly everywhere on the screen, presumably because of rounding issues...

Then I considered why simply not keeping integers as that would be simpler but also not introduce subtle bugs that will be hard to track.

This is an example of how the code is, many things are updated against frame rate ratios:

playerShip.ThrustMagnitude += Timing.Instance.FR15 + 1;

I came up with the following which works well in some cases but not all:

playerShip.ThrustMagnitude += Timing.Scale(Timing.Instance.FR15 + 1, deltaTime);

The helper class in its entirety:

public sealed class Timing : Singleton<Timing>
{
    public static double OriginalFrameRate { get; } = 1.0d / 30.0d;
    public int FR6 { get; } = 6;
    public int FR7 { get; } = 7;
    public int FR10 { get; } = 10;
    public int FR15 { get; } = 15;
    public int FR30 { get; } = 30;
    public int FR32 { get; } = 32;
    public int FR40 { get; } = 40;
    public int FR50 { get; } = 50;
    public int FR60 { get; } = 60;
public static int Scale(int value, double deltaTime, int? decimals = null, MidpointRounding? rounding = null)
{
    var result = deltaTime / OriginalFrameRate * value;

    if (decimals.HasValue)
    {
        var digits = decimals.Value;

        if (rounding.HasValue)
        {
            result = Math.Round(result, digits, rounding.Value);
        }
        else
        {
            result = Math.Round(result, digits);
        }
    }
    return (int)result;
}

}

The main problem I have is that it doesn't work when values are very small, yaw and roll for instance work well because they have large values, but the pitch for instance does not because its range is very small.

Say you have a value of 30 at 30 FPS, X / 30 == 1, but at 60 FPS it results in X / 60 == 0.

What approach can you suggest to tackle this problem?

Kromster
  • 10,643
  • 4
  • 53
  • 67
Eric Cartman
  • 773
  • 6
  • 22
  • @DMGregory Looking into it, thank you. – Eric Cartman Jan 10 '23 at 13:37
  • @Philipp I used to think like so but the guys probably had a good reason to, some might certainly explain that way better than I would. Now just ask yourself, isn't it even more stupid to try to convert it to floats while it's working perfectly with ints? I used to believe in that but then realize that it might not be the brightest idea because it's way trickier than it seems. – Eric Cartman Jan 10 '23 at 13:41
  • 1
    @aybe Without access to the complete codebase I can only guess, but one possible source of bugs in such a conversion are equality checks. While checking two integers for equality can make sense, checking two floats for equality often does not, because the CPU can't tell the difference between "clearly different" and "functionally equivalent, but technically different due to a tiny rounding error". And rounding errors occur a lot with floats (see https://floating-point-gui.de). – Philipp Jan 10 '23 at 14:03