am trying to do something that should be quite common in games: Applying a factor over a certain amount of time. For example let's say a number should become a quarter of itself every second.
How do we do this with variable frame rate?
I have written the following code:
using System;
public class Program
{
static double NthRoot(double x, double n)
{
return Math.Pow(x, 1.0f / n);
}
public static void Main()
{
double input = 10;
double factor = 0.25;
Console.WriteLine("Direct result: " + (input * factor));
Random rnd = new Random();
// simulate everything five times
for (int i = 0; i < 5; i++)
{
double val = input;
double total_time = 0;
// simulate the frames that accumulate to one second
while(total_time < 1.0)
{
// simulate a delta time for the current frame
double delta = rnd.Next(50, 100)/1000.0;
total_time += delta;
double current_frames = 1.0/delta;
// apply the current factor
val *= Program.NthRoot(factor, current_frames);
}
Console.WriteLine("Result over one second: " + val);
}
}
It produces a random delta (as if frame rate were fluctuating) and calculates a special factor for every frame based on the framerate derived by this delta time.
However the results are inaccurate and tend to be too small:
Direct result: 2.5
Result over one second: 2.37171078785113
Result over one second: 2.36842517649817
Result over one second: 2.4655817612334
Result over one second: 2.34555299125168
Result over one second: 2.38820734095609
Here a Fiddle for the code: https://dotnetfiddle.net/1tEXba
How does one do this more accurately?
Huge thanks!
total_time<1.0
when your loop quits. If you addval *= Program.NthRoot(factor, 1.0 / (1.0 - total_time));
before printing the result, you ensure that you run the simulation for a full second and always get the 2.5 you wanted: ideone.com/72yH0S \$\endgroup\$total_time<1.0
when the loop enters for the last time. Then we add a random value 0.050-0.099 to it. So we might simulate a total of between 1.000 seconds (if our last random amount was just exactly enough to meet the exit condition) and 1.098 seconds (if our total had been 0.999 before the final loop and we rolled the max). So usually we end up with more than a full second of simulation by the time the loop exits. The code addition you have there adds some "negative time" to rewind the spillover back to 1.0. \$\endgroup\$