
com.almasb.fxgl.animation.AnimatedValue.kt Maven / Gradle / Ivy
The newest version!
/*
* FXGL - JavaFX Game Library. The MIT License (MIT).
* Copyright (c) AlmasB ([email protected]).
* See LICENSE for details.
*/
package com.almasb.fxgl.animation
import com.almasb.fxgl.core.math.FXGLMath
import javafx.animation.Interpolator
import javafx.animation.PathTransition
import javafx.geometry.Point2D
import javafx.geometry.Point3D
import javafx.scene.paint.Color
import javafx.scene.shape.CubicCurve
import javafx.scene.shape.QuadCurve
import javafx.scene.shape.Rectangle
import javafx.scene.shape.Shape
import javafx.util.Duration
import kotlin.math.max
import kotlin.math.min
/**
* A value that can be animated (progressed) from value1 to value 2.
* An interpolator can be used to control the rate of animation (progression).
*
* @author Almas Baimagambetov ([email protected])
*/
open class AnimatedValue(val from: T, val to: T) {
fun getValue(progress: Double): T {
return animate(from, to, progress, Interpolator.LINEAR)
}
fun getValue(progress: Double, interpolator: Interpolator): T {
return animate(from, to, progress, interpolator)
}
@Suppress("UNCHECKED_CAST")
open fun animate(val1: T, val2: T, progress: Double, interpolator: Interpolator): T {
return interpolator.interpolate(val1, val2, progress) as T
}
}
class AnimatedPoint2D(from: Point2D, to: Point2D)
: AnimatedValue(from, to) {
override fun animate(val1: Point2D, val2: Point2D, progress: Double, interpolator: Interpolator): Point2D {
return interpolate(val1, val2, progress, interpolator)
}
private fun interpolate(fromValue: Point2D, toValue: Point2D, progress: Double, interpolator: Interpolator): Point2D {
val x = interpolator.interpolate(fromValue.x, toValue.x, progress)
val y = interpolator.interpolate(fromValue.y, toValue.y, progress)
return Point2D(x, y)
}
}
class AnimatedPoint3D(from: Point3D, to: Point3D)
: AnimatedValue(from, to) {
override fun animate(val1: Point3D, val2: Point3D, progress: Double, interpolator: Interpolator): Point3D {
return interpolate(val1, val2, progress, interpolator)
}
private fun interpolate(fromValue: Point3D, toValue: Point3D, progress: Double, interpolator: Interpolator): Point3D {
val x = interpolator.interpolate(fromValue.x, toValue.x, progress)
val y = interpolator.interpolate(fromValue.y, toValue.y, progress)
val z = interpolator.interpolate(fromValue.z, toValue.z, progress)
return Point3D(x, y, z)
}
}
class AnimatedQuadBezierPoint2D
(val path: QuadCurve) : AnimatedValue(Point2D.ZERO, Point2D.ZERO) {
override fun animate(val1: Point2D, val2: Point2D, progress: Double, interpolator: Interpolator): Point2D {
return FXGLMath.bezier(
Point2D(path.startX, path.startY),
Point2D(path.controlX, path.controlY),
Point2D(path.endX, path.endY),
interpolator.interpolate(0.0, 1.0, progress)
)
}
}
class AnimatedCubicBezierPoint2D
(val path: CubicCurve) : AnimatedValue(Point2D.ZERO, Point2D.ZERO) {
override fun animate(val1: Point2D, val2: Point2D, progress: Double, interpolator: Interpolator): Point2D {
return FXGLMath.bezier(
Point2D(path.startX, path.startY),
Point2D(path.controlX1, path.controlY1),
Point2D(path.controlX2, path.controlY2),
Point2D(path.endX, path.endY),
interpolator.interpolate(0.0, 1.0, progress)
)
}
}
internal class AnimatedQuadBezierPoint3D
(val path: QuadCurve) : AnimatedValue(Point3D.ZERO, Point3D.ZERO) {
private val animated2D = AnimatedQuadBezierPoint2D(path)
override fun animate(val1: Point3D, val2: Point3D, progress: Double, interpolator: Interpolator): Point3D {
val p = animated2D.animate(Point2D(val1.x, val1.y), Point2D(val2.x, val2.y), progress, interpolator)
return Point3D(p.x, p.y, 0.0)
}
}
internal class AnimatedCubicBezierPoint3D
(val path: CubicCurve) : AnimatedValue(Point3D.ZERO, Point3D.ZERO) {
private val animated2D = AnimatedCubicBezierPoint2D(path)
override fun animate(val1: Point3D, val2: Point3D, progress: Double, interpolator: Interpolator): Point3D {
val p = animated2D.animate(Point2D(val1.x, val1.y), Point2D(val2.x, val2.y), progress, interpolator)
return Point3D(p.x, p.y, 0.0)
}
}
class AnimatedColor(from: Color, to: Color)
: AnimatedValue(from, to) {
override fun animate(val1: Color, val2: Color, progress: Double, interpolator: Interpolator): Color {
return Color.color(
interpolator.interpolate(val1.red, val2.red, progress),
interpolator.interpolate(val1.green, val2.green, progress),
interpolator.interpolate(val1.blue, val2.blue, progress),
interpolator.interpolate(val1.opacity, val2.opacity, progress)
)
}
}
class AnimatedPath
(val path: Shape) : AnimatedValue(Point3D.ZERO, Point3D.ZERO) {
/**
* Maps reference time values [0..1] to points on path at that time.
*/
private val points = hashMapOf()
init {
val dummy = Rectangle()
val pt = PathTransition(Duration.seconds(1.0), path, dummy)
pt.play()
var t = 0.0
var percent = 0
while (t < 1.0) {
points[percent++] = Point3D(dummy.translateX, dummy.translateY, 0.0)
t += 0.01
pt.jumpTo(Duration.seconds(t))
}
pt.jumpTo(Duration.seconds(1.0))
// hack to ensure that points[0] is not (0, 0)
points[0] = points[1]!!
points[100] = Point3D(dummy.translateX, dummy.translateY, 0.0)
}
override fun animate(val1: Point3D, val2: Point3D, progress: Double, interpolator: Interpolator): Point3D {
val t = interpolator.interpolate(0.0, 1.0, progress)
val key = (t * 100).toInt()
return points[key]!!
}
}
class AnimatedStringIncreasing(value: String) : AnimatedValue("", value) {
override fun animate(val1: String, val2: String, progress: Double, interpolator: Interpolator): String {
var index = (val2.length * interpolator.interpolate(0.0, 1.0, progress)).toInt()
index = max(index, 0)
index = min(index, val2.length)
return val2.substring(0, index)
}
}
class AnimatedStringDecreasing(value: String) : AnimatedValue("", value) {
private val anim = AnimatedStringIncreasing(value)
override fun animate(val1: String, val2: String, progress: Double, interpolator: Interpolator): String {
return anim.animate(val1, val2, 1 - progress, interpolator)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy