Skip to content

Commit 211e867

Browse files
committed
fixed non-uniform frame distribution for AnimationTexture, closes #1067
1 parent 7a40f5d commit 211e867

1 file changed

Lines changed: 58 additions & 1 deletion

File tree

fxgl-core/src/main/kotlin/com/almasb/fxgl/texture/AnimatedTexture.kt

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,68 @@ class AnimatedTexture(defaultChannel: AnimationChannel) : Texture(defaultChannel
166166
}
167167
.duration(Duration.seconds(animationChannel.frameDuration * animationChannel.sequence.size))
168168
.interpolator(interpolator)
169-
.animate(AnimatedValue(0, animationChannel.sequence.size - 1))
169+
.animate(PreciseAnimatedIntValue(0, animationChannel.sequence.size - 1))
170170
.onProgress { frameNum ->
171171
currentFrame = min(frameNum, animationChannel.sequence.size - 1)
172172
updateImage()
173173
}
174174
.build()
175175
}
176+
}
177+
178+
/**
179+
* This animated value provides higher accuracy for mapping progress to an int value.
180+
*
181+
* For example, the default AnimatedValue results for [0,3] (non-uniform!):
182+
0.00: 0
183+
0.05: 0
184+
0.10: 0
185+
0.15: 0
186+
187+
0.20: 1
188+
0.25: 1
189+
0.30: 1
190+
0.35: 1
191+
0.40: 1
192+
0.45: 1
193+
194+
0.50: 2
195+
0.55: 2
196+
0.60: 2
197+
0.65: 2
198+
0.70: 2
199+
0.75: 2
200+
0.80: 2
201+
202+
0.85: 3
203+
0.90: 3
204+
0.95: 3
205+
1.00: 3
206+
*/
207+
private class PreciseAnimatedIntValue(start: Int, end: Int) : AnimatedValue<Int>(start, end) {
208+
209+
private val mapping = linkedMapOf<ClosedFloatingPointRange<Double>, Int>()
210+
211+
init {
212+
val numSegments = end - start + 1
213+
val progressPerSegment = 1.0 / numSegments
214+
215+
var progress = 0.0
216+
217+
for (i in start..end) {
218+
val progressEnd = if (i == end) 1.0 else (progress + progressPerSegment)
219+
220+
mapping[progress..progressEnd] = i
221+
222+
progress += progressPerSegment
223+
}
224+
}
225+
226+
override fun animate(val1: Int, val2: Int, progress: Double, interpolator: Interpolator): Int {
227+
val p = interpolator.interpolate(0.0, 1.0, progress)
228+
229+
return mapping.filterKeys { p in it }
230+
.values
231+
.firstOrNull() ?: val1
232+
}
176233
}

0 commit comments

Comments
 (0)