using System; namespace Luneraria.View { /// /// Fixed simulation tick (U2C): frame time goes into an accumulator, and whole steps of /// LuneBalance.SimStep (0.05 s) come out. The frame rate only decides how many steps run in a /// frame, never what a step does, so every frame rate produces the same sequence of steps. /// Alpha is the fraction of the next step already elapsed; views interpolate with it. /// public sealed class LuneClock { public readonly double Step; /// Upper bound per frame; a stalled frame is caught up over the next frames. public int MaxStepsPerFrame = 200; double _accumulator; public LuneClock(double step) { Step = step; } public double Alpha { get { return Math.Min(1.0, _accumulator / Step); } } public void Reset() { _accumulator = 0.0; } /// Adds frame time and runs whole steps; step returns false when it has to stop. public int Advance(double seconds, Func step) { if (seconds > 0.0) _accumulator += seconds; int count = 0; while (_accumulator >= Step && count < MaxStepsPerFrame) { _accumulator -= Step; count++; if (!step()) { _accumulator = 0.0; break; } } return count; } } }