Skip to content

Commit

Permalink
Improve interpolation smoothing example
Browse files Browse the repository at this point in the history
Improves explanation of interpolation ("lerp") smoothing.
Adds a note about framerate-independent version, with off-site links to
full explanations.

Co-Authored-By: aXu-AP <[email protected]>
  • Loading branch information
tetrapod00 and aXu-AP committed Nov 3, 2024
1 parent 717d603 commit f5523ec
Showing 1 changed file with 50 additions and 2 deletions.
52 changes: 50 additions & 2 deletions tutorials/math/interpolation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ And again, it will produce the following motion:
Smoothing motion
----------------

Interpolation can be used to smooth movement, rotation, etc. Here is an example of a circle following the mouse using smoothed motion:
Interpolation can be used to smoothly follow a moving target value, such as a
position or a rotation. Each frame, ``lerp()`` moves the current value towards
the target value by a fixed percentage of the remaining difference between the values.
The current value will smoothly move towards the target, slowing down as it gets
closer. Here is an example of a circle following the mouse using interpolation smoothing:

.. tabs::
.. code-tab:: gdscript GDScript
Expand Down Expand Up @@ -138,4 +142,48 @@ Here is how it looks:

.. image:: img/interpolation_follow.gif

This is useful for smoothing camera movement, allies following you (ensuring they stay within a certain range), and many other common game patterns.
This is useful for smoothing camera movement, for allies following the player
(ensuring they stay within a certain range), and for many other common game patterns.

.. note::
Despite using ``delta``, the formula used above is framerate-dependent, because
the ``weight`` parameter of ``lerp()`` represents a *percentage* of the remaining
difference in values, not an *absolute amount to change*. In ``_physics_process()``,
this is usually fine because physics is expected to maintain a constant framerate,
and therefore ``delta`` is expected to remain constant. For example, with an FPS
of ``60`` and a ``FOLLOW_SPEED`` of ``4.0``, ``delta`` will be ``1/60`` or ``0.0166``,
and ``FOLLOW_SPEED * delta`` will be a constant value of ``0.0666``.

For a framerate-independent version of interpolation smoothing that can be used
in ``process()``, use the following formula instead:

.. tabs::
.. code-tab:: gdscript GDScript

const FOLLOW_SPEED = 4.0

func _process(delta):
var mouse_pos = get_local_mouse_position()
var weight = 1 - exp(-FOLLOW_SPEED * delta)
$Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, weight)

.. code-tab:: csharp

private const float FollowSpeed = 4.0f;

public override void _Process(double delta)
{
Vector2 mousePos = GetLocalMousePosition();

Sprite2D sprite = GetNode<Sprite2D>("Sprite2D");
float weight = 1f - Mathf.Exp(-FollowSpeed * (float)delta);
sprite.Position = sprite.Position.Lerp(mousePos, weight);
}

Deriving this formula is beyond the scope of this page. For an explanation,
read `Improved Lerp Smoothing <https://www.gamedeveloper.com/programming/improved-lerp-smoothing->`__
or watch `Lerp smoothing is broken <https://www.youtube.com/watch?v=LSNQuFEDOyQ>`__.




0 comments on commit f5523ec

Please sign in to comment.