  Android Code Snippet [LibGDX CatMullRomSpline] Constant Speed Progress Calculator

Discussion in 'Code Snippets' started by wonder, May 24, 2019.

1. Hi!

If you ever encounter the problem described on the link below, you can use this class to solve this problem:
https://stackoverflow.com/questions/32665262/libgdx-path-catmullromspline-constant-speed

Class Module: ConstSpeedProgressCalculator
Code:
Private Sub Class_Globals

Private ref                 As Reflector

Private derivative_average  As Float

Private path_completion     As Float

Private derivative          As lgMathVector2
End Sub

Public Sub Initialize(spline As lgMathCatmullRomSpline, samples As Int)
ref.Target = spline.InternalObject

Dim out As lgMathVector2

Dim f = 0 As Float

Do While f < 1
out = DerivativeAt(out, f)
derivative_average = derivative_average + out.len
f = f + (
1 / samples)

Loop
derivative_average = derivative_average / samples
End Sub

Public Sub Update(speed As Float, deltatime As Float, reset_automatically As Boolean)
derivative = DerivativeAt(derivative, path_completion)
path_completion = path_completion + (derivative_average * speed * deltatime / derivative.len)

If reset_automatically Then path_completion = path_completion Mod 1
End Sub

Public Sub getPathCompletion As Float

Return path_completion
End Sub

Public Sub Reset
path_completion =
0
End Sub

Private Sub DerivativeAt(out As lgMathVector2, completion As Float) As lgMathVector2

Return ref.RunMethod4("derivativeAt"Array(out, completion), Array As String("java.lang.Object""java.lang.float"))
End Sub

Usage:

1. Declare the ProgressCalculator instance as a global (recommended):
Code:
Sub Process_Globals
...

Private ProgressCalculator As ConstSpeedProgressCalculator
...
End Sub

2. Initialize the class right after you initialize the spline.
Code:
ProgressCalculator.Initialize(mySpline, 100'more samples = smoother result

3. Replace, on your update method (or whatever it's named), the usual:
Code:
progress = progress + (lGdx.graphics.DeltaTime * speed) 'Value between 0 and 1
with:
Code:
ProgressCalculator.Update(speed, lGdx.graphics.DeltaTime, False'or True
progress = ProgressCalculator.PathCompletion 'Value between 0 and 1

Code:
...

Sub InitializeSpline(s As lgMathCatmullRomSplineAs Boolean

If nodes.Length < 4 Then Return False
s.Initialize(Utils.MathVec2Array(nodes),
False)

Return True
End Sub

Sub InitializePathPreview As Boolean
preview_timestamp =
0
preview_completion =
0
preview_path_complete =
False
active_path = Paths.get(SelectedPath.Number)
nodes = Utils.ExtrapolatedPath(active_path.nodes)

Dim result = InitializeSpline(preview_spline) As Boolean

If result Then preview_progress_calc.Initialize(preview_spline, 100)

Return result
End Sub

Sub DrawPathPreview(shape_renderer As lgShapeRenderer, viewport As Rect)

If SelectedPath.IsUpdated(TrueThen InitializePathPreview

If Not(active_path.IsInitialized)          _

Or Not(active_path.Settings.IsInitialized) _

Or active_path.Settings.Size == 0          _

Or SelectedPath.Number < 0                 _

Or nodes.Length < 4 Then Return            _

'-------------------------------------------

Dim speed = Utils.ToNumber(active_path.Settings.Get          ("speed"        )) * 0.5  As Double

Dim itrpl = Maps.Interpolation.Get(active_path.Settings.Get  ("interpolation"))        As lgMathInterpolation

If preview_path_complete Then
preview_timestamp =
0
preview_completion =
0
preview_progress_calc.Reset
preview_path_complete =
False

End If

Dim delay = 300 * 1 / speed As Int

Dim shape_size As Double

Dim multiplier As Double

Dim min_shape_size = Constants.ENDNODE_RADIUS / 3 As Double

If preview_completion >= 1 Then
ApplyPreviewPathDelay(delay)
multiplier =
Min(delay, DateTime.Now - preview_timestamp) / delay
shape_size = min_shape_size + ((Constants.ENDNODE_RADIUS - min_shape_size) * multiplier)
preview_spline_motion.Set(active_path.LastNode.x, active_path.LastNode.y)

Else
multiplier =
0
shape_size = min_shape_size
preview_progress_calc.Update(speed, volume.LibGDX.Graphics.DeltaTime,
False)
preview_completion = preview_progress_calc.PathCompletion
preview_spline.ValueAt(preview_spline_motion, itrpl.apply(preview_completion))

End If

shape_renderer.Begin(shape_renderer.SHAPETYPE_Filled)
shape_renderer.SetColorRGBA(
1.00.00.01.0 * (1 - multiplier))
shape_renderer.Circle(                          _
viewport.CenterX + preview_spline_motion.x, _
viewport.CenterY + preview_spline_motion.y, _
shape_size                                  _
)
shape_renderer.End
End Sub

Sub ApplyPreviewPathDelay(delay As Int)

If preview_timestamp == 0 Then
preview_timestamp =
DateTime.now

else if DateTime.Now - preview_timestamp >= delay Then
preview_timestamp =
0
preview_path_complete =
True

End If
End Sub

...

Last edited: May 29, 2019
José J. Aguilar likes this.