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
Usage:
1. Declare the ProgressCalculator instance as a global (recommended):
2. Initialize the class right after you initialize the spline.
3. Replace, on your update method (or whatever it's named), the usual:
with:
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
B4X:
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):
B4X:
Sub Process_Globals
...
Private ProgressCalculator As ConstSpeedProgressCalculator
...
End Sub
2. Initialize the class right after you initialize the spline.
B4X:
ProgressCalculator.Initialize(mySpline, 100) 'more samples = smoother result
3. Replace, on your update method (or whatever it's named), the usual:
B4X:
progress = progress + (lGdx.graphics.DeltaTime * speed) 'Value between 0 and 1
B4X:
ProgressCalculator.Update(speed, lGdx.graphics.DeltaTime, False) 'or True
progress = ProgressCalculator.PathCompletion 'Value between 0 and 1
B4X:
...
Sub InitializeSpline(s As lgMathCatmullRomSpline) As 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(True) Then 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.0, 0.0, 0.0, 1.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: