Skip to content

Commit

Permalink
Improve gliding at non-60FPS (#1600)
Browse files Browse the repository at this point in the history
* Use the frame delta when moving glides

* Change `MovementPerFrame` name to `MovementSpeed`
  • Loading branch information
wixoaGit authored Jan 1, 2024
1 parent f63978a commit c1d4fab
Showing 1 changed file with 14 additions and 19 deletions.
33 changes: 14 additions & 19 deletions OpenDreamClient/Rendering/AtomGlideSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ namespace OpenDreamClient.Rendering;
/// Disables RobustToolbox's transform lerping and replaces it with our own gliding
/// </summary>
public sealed class AtomGlideSystem : EntitySystem {
private sealed class Glide {
public readonly TransformComponent Transform;
private sealed class Glide(TransformComponent transform) {
public readonly TransformComponent Transform = transform;
public Vector2 EndPos;
public float MovementPerFrame;

public Glide(TransformComponent transform) {
Transform = transform;
}
public float MovementSpeed;
}

[Dependency] private readonly TransformSystem _transformSystem = default!;
Expand Down Expand Up @@ -48,21 +44,22 @@ public override void FrameUpdate(float frameTime) {
var glide = _currentGlides[i];
var currentPos = glide.Transform.LocalPosition;
var newPos = currentPos;
var movement = glide.MovementSpeed * frameTime;

// Move X towards the end position at a constant speed
if (!MathHelper.CloseTo(currentPos.X, glide.EndPos.X)) {
if (currentPos.X < glide.EndPos.X)
newPos.X = Math.Min(glide.EndPos.X, newPos.X + glide.MovementPerFrame);
newPos.X = Math.Min(glide.EndPos.X, newPos.X + movement);
else if (currentPos.X > glide.EndPos.X)
newPos.X = Math.Max(glide.EndPos.X, newPos.X - glide.MovementPerFrame);
newPos.X = Math.Max(glide.EndPos.X, newPos.X - movement);
}

// Move Y towards the end position at a constant speed
if (!MathHelper.CloseTo(currentPos.Y, glide.EndPos.Y)) {
if (currentPos.Y < glide.EndPos.Y)
newPos.Y = Math.Min(glide.EndPos.Y, newPos.Y + glide.MovementPerFrame);
newPos.Y = Math.Min(glide.EndPos.Y, newPos.Y + movement);
else if (currentPos.Y > glide.EndPos.Y)
newPos.Y = Math.Max(glide.EndPos.Y, newPos.Y - glide.MovementPerFrame);
newPos.Y = Math.Max(glide.EndPos.Y, newPos.Y - movement);
}

if (newPos.EqualsApprox(glide.EndPos)) { // Glide is finished
Expand All @@ -84,7 +81,7 @@ public override void FrameUpdate(float frameTime) {
private void OnTransformMove(ref MoveEvent e) {
if (_ignoreMoveEvent || e.ParentChanged)
return;
if (!_spriteQuery.TryGetComponent(e.Sender, out var sprite))
if (!_spriteQuery.TryGetComponent(e.Sender, out var sprite) || sprite.Icon?.Appearance is null)
return;

_ignoreMoveEvent = true;
Expand Down Expand Up @@ -123,18 +120,16 @@ private void OnTransformMove(ref MoveEvent e) {
_transformSystem.SetLocalPositionNoLerp(e.Sender, startingFrom, e.Component);

glide.EndPos = glidingTo;
glide.MovementPerFrame = CalculateMovementPerFrame(sprite.Icon.Appearance.GlideSize);
glide.MovementSpeed = CalculateMovementSpeed(sprite.Icon.Appearance.GlideSize);
_ignoreMoveEvent = false;
}

private static float CalculateMovementPerFrame(byte glideSize) {
private static float CalculateMovementSpeed(byte glideSize) {
if (glideSize == 0)
glideSize = 4; // TODO: 0 gives us "automated control" over this value, not just setting it to 4

// Assume a 60 FPS client and a 20 TPS server
// TODO: Support other FPS and TPS
var scaling = (60f / 20f);

return glideSize / scaling / EyeManager.PixelsPerMeter;
// Assume a 20 TPS server
// TODO: Support other TPS
return (float)glideSize / EyeManager.PixelsPerMeter * 20f;
}
}

0 comments on commit c1d4fab

Please sign in to comment.