210 lines
5.7 KiB
Java
210 lines
5.7 KiB
Java
package com.atsuishio.superbwarfare.tools.animation;
|
||
|
||
import net.minecraft.util.Mth;
|
||
|
||
import java.util.function.Function;
|
||
|
||
/**
|
||
* 可以更改计时方向的动画计时器
|
||
*/
|
||
public class AnimationTimer {
|
||
private final long duration;
|
||
private long startTime;
|
||
private boolean reversed;
|
||
private boolean initialized;
|
||
private boolean isStart = true;
|
||
|
||
private Function<Double, Double> forwardAnimationCurve = AnimationCurves.LINEAR;
|
||
private Function<Double, Double> backwardAnimationCurve = AnimationCurves.LINEAR;
|
||
|
||
/**
|
||
* 创建一个动画计时器
|
||
*
|
||
* @param duration 动画持续时间,单位为毫秒
|
||
*/
|
||
public AnimationTimer(long duration) {
|
||
this.duration = duration;
|
||
}
|
||
|
||
/**
|
||
* 设置正向和反向计时时采用的动画曲线
|
||
*/
|
||
public AnimationTimer animation(Function<Double, Double> animationCurve) {
|
||
return this.forwardAnimation(animationCurve).backwardAnimation(animationCurve);
|
||
}
|
||
|
||
/**
|
||
* 设置反向计时时采用的动画曲线
|
||
*/
|
||
public AnimationTimer forwardAnimation(Function<Double, Double> animationCurve) {
|
||
this.forwardAnimationCurve = animationCurve;
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* 设置反向计时时采用的动画曲线
|
||
*/
|
||
|
||
public AnimationTimer backwardAnimation(Function<Double, Double> animationCurve) {
|
||
this.backwardAnimationCurve = animationCurve;
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* 创建多个线性动画计时器
|
||
*
|
||
* @param size 计时器数量
|
||
* @param duration 动画持续时间,单位为毫秒
|
||
*/
|
||
|
||
public static AnimationTimer[] createTimers(int size, long duration) {
|
||
return createTimers(size, duration, AnimationCurves.LINEAR);
|
||
}
|
||
|
||
/**
|
||
* 创建多个动画计时器
|
||
*
|
||
* @param size 计时器数量
|
||
* @param duration 动画持续时间,单位为毫秒
|
||
* @param animationCurve 动画曲线函数
|
||
*/
|
||
public static AnimationTimer[] createTimers(int size, long duration, Function<Double, Double> animationCurve) {
|
||
return createTimers(size, duration, animationCurve, animationCurve);
|
||
}
|
||
|
||
/**
|
||
* 创建多个动画计时器
|
||
*
|
||
* @param size 计时器数量
|
||
* @param duration 动画持续时间,单位为毫秒
|
||
* @param forwardAnimationCurve 正向动画曲线函数
|
||
* @param backwardAnimationCurve 反向动画曲线函数
|
||
*/
|
||
public static AnimationTimer[] createTimers(int size, long duration, Function<Double, Double> forwardAnimationCurve, Function<Double, Double> backwardAnimationCurve) {
|
||
var timers = new AnimationTimer[size];
|
||
var currentTime = System.currentTimeMillis();
|
||
for (int i = 0; i < size; i++) {
|
||
timers[i] = new AnimationTimer(duration).forwardAnimation(forwardAnimationCurve).backwardAnimation(backwardAnimationCurve);
|
||
timers[i].endBackward(currentTime);
|
||
}
|
||
return timers;
|
||
}
|
||
|
||
/**
|
||
* 当前计时方向是否为正向
|
||
*/
|
||
public boolean isForward() {
|
||
return !reversed;
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取当前进度
|
||
*
|
||
* @return 进度值,范围在0到1之间
|
||
*/
|
||
public float getProgress(long currentTime) {
|
||
if (reversed) {
|
||
return 1 - backwardAnimationCurve.apply(Mth.clamp(1 - getElapsedTime(currentTime) / (double) duration, 0, 1)).floatValue();
|
||
} else {
|
||
return forwardAnimationCurve.apply(Mth.clamp(getElapsedTime(currentTime) / (double) duration, 0, 1)).floatValue();
|
||
}
|
||
}
|
||
|
||
private long getElapsedTime(long currentTime) {
|
||
if (!initialized) return 0;
|
||
|
||
if (reversed) {
|
||
return Math.min(duration, Math.max(0, startTime - currentTime));
|
||
} else {
|
||
return Math.min(duration, currentTime - startTime);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 当前动画是否已经结束
|
||
*/
|
||
public boolean finished(long currentTime) {
|
||
return getProgress(currentTime) >= 1;
|
||
}
|
||
|
||
/**
|
||
* 将计时器设置为开始状态
|
||
*/
|
||
public void begin() {
|
||
initialized = false;
|
||
isStart = true;
|
||
}
|
||
|
||
/**
|
||
* 将计时器设置为结束状态
|
||
*/
|
||
public void end() {
|
||
initialized = false;
|
||
isStart = false;
|
||
}
|
||
|
||
/**
|
||
* 将计时方向更改为正向
|
||
*/
|
||
public void forward(long currentTime) {
|
||
if (!initialized) {
|
||
initialized = true;
|
||
startTime = currentTime + (isStart ? 0 : duration);
|
||
} else if (reversed) {
|
||
startTime = currentTime - getElapsedTime(currentTime);
|
||
}
|
||
reversed = false;
|
||
}
|
||
|
||
/**
|
||
* 开始正向计时
|
||
*/
|
||
|
||
public void beginForward(long currentTime) {
|
||
begin();
|
||
forward(currentTime);
|
||
}
|
||
|
||
/**
|
||
* 结束正向计时
|
||
*/
|
||
public void endForward(long currentTime) {
|
||
end();
|
||
forward(currentTime);
|
||
}
|
||
|
||
/**
|
||
* 将计时方向更改为反向
|
||
*/
|
||
public void backward(long currentTime) {
|
||
if (!initialized) {
|
||
initialized = true;
|
||
startTime = currentTime + (isStart ? duration : 0);
|
||
} else if (!reversed) {
|
||
startTime = currentTime + getElapsedTime(currentTime);
|
||
}
|
||
reversed = true;
|
||
}
|
||
|
||
/**
|
||
* 开始反向计时
|
||
*/
|
||
public void beginBackward(long currentTime) {
|
||
begin();
|
||
backward(currentTime);
|
||
}
|
||
|
||
/**
|
||
* 结束反向计时
|
||
*/
|
||
public void endBackward(long currentTime) {
|
||
end();
|
||
backward(currentTime);
|
||
}
|
||
|
||
public float lerp(float start, float end, long currentTime) {
|
||
return Mth.lerp(getProgress(currentTime), start, end);
|
||
}
|
||
|
||
}
|