Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ShapeEngine/Core/GameDef/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public partial class Game
/// This value is calculated as 1.0 / FixedPhysicsFramerate and represents
/// the duration of each physics step in seconds.
/// </remarks>
public float FixedPhysicsTimestep { get; private set; }
public double FixedPhysicsTimestep { get; private set; }

/// <summary>
/// Gets the game time information for the variable update loop.
Expand Down Expand Up @@ -348,7 +348,7 @@ private bool IsIdleFrameRateLimitActive()
private readonly List<ShapeFlash> shapeFlashes = [];
private readonly List<DeferredInfo> deferred = [];

private float physicsAccumulator;
private double physicsAccumulator;

private List<ScreenTexture>? customScreenTextures;
#endregion
Expand Down Expand Up @@ -540,7 +540,7 @@ public Game(GameSettings gameSettings, WindowSettings windowSettings, InputSetti
{
if (fixedFramerate < 30) fixedFramerate = 30;
FixedPhysicsFramerate = fixedFramerate;
FixedPhysicsTimestep = 1f / FixedPhysicsFramerate;
FixedPhysicsTimestep = 1.0 / FixedPhysicsFramerate;
FixedPhysicsEnabled = true;
}

Expand Down
19 changes: 11 additions & 8 deletions ShapeEngine/Core/GameDef/GameGameloop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ private void RunGameloop()
if (FixedPhysicsEnabled)
{
ResolveUpdate(true);
AdvanceFixedUpdate(dt);
// Use double-precision frameDelta for more accurate fixed-step physics timing
AdvanceFixedUpdate(frameDelta);
}
else ResolveUpdate(false);

Expand Down Expand Up @@ -341,25 +342,27 @@ private void GameTextureOnTextureResized(int w, int h)
ResolveOnGameTextureResized(w, h);
}

private void AdvanceFixedUpdate(float dt)
private void AdvanceFixedUpdate(double dt)
{
const float maxFrameTime = 1f / 30f;
float frameTime = dt;
// var t = 0.0f;
const double maxFrameTime = 1.0 / 30.0;
double frameTime = dt;

if (frameTime > maxFrameTime) frameTime = maxFrameTime;

physicsAccumulator += frameTime;
while (physicsAccumulator >= FixedPhysicsTimestep)
{
FixedTime = FixedTime.TickF(FixedPhysicsFramerate);
FixedTime = FixedTime.Tick(FixedPhysicsTimestep);
ResolveFixedUpdate();
// t += FixedPhysicsTimestep;
physicsAccumulator -= FixedPhysicsTimestep;
}

float alpha = physicsAccumulator / FixedPhysicsTimestep;
ResolveInterpolateFixedUpdate(alpha);
double alpha = physicsAccumulator / FixedPhysicsTimestep;
// alpha is computed in double precision for timing accuracy, but interpolation
// uses float because ResolveInterpolateFixedUpdate (e.g., via IUpdateable) has
// a float-based public API. This precision downgrade is intentional.
ResolveInterpolateFixedUpdate((float)alpha);
}

}
9 changes: 9 additions & 0 deletions ShapeEngine/Core/Structs/GameTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ public GameTime(double totalSeconds, int totalFrames, double elapsedSeconds)
/// </summary>
public readonly float Delta => (float)ElapsedSeconds;

/// <summary>
/// Gets the elapsed time since the last frame as a double-precision value.
/// </summary>
/// <remarks>
/// Use <see cref="DeltaDouble"/> when double precision is required instead of the single-precision <see cref="Delta"/>.
/// This property simply returns the underlying <see cref="ElapsedSeconds"/> value.
/// </remarks>
public readonly double DeltaDouble => ElapsedSeconds;

/// <summary>
/// Gets the current frames per second (FPS) based on the elapsed time between frames.
/// </summary>
Expand Down
Loading