优化动画曲线

This commit is contained in:
Light_Quanta 2025-03-20 10:16:31 +08:00
parent c95fefe681
commit c237cca842
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
5 changed files with 49 additions and 22 deletions

View file

@ -211,7 +211,9 @@ public class AmmoBarOverlay {
} }
} }
private static final AnimationTimer ammoInfoTimer = new AnimationTimer(500, AnimationCurves.EASE_OUT_CIRC); private static final AnimationTimer ammoInfoTimer = new AnimationTimer(1500)
.forwardAnimation(AnimationCurves.EASE_OUT_EXPO)
.backwardAnimation(AnimationCurves.EASE_IN_EXPO);
/** /**
* 在手持弹药或弹药盒时渲染玩家弹药总量信息 * 在手持弹药或弹药盒时渲染玩家弹药总量信息

View file

@ -71,7 +71,7 @@ public class VehicleHudOverlay {
private static boolean lastTimeRenderingWeapons = false; private static boolean lastTimeRenderingWeapons = false;
private static int lastTimeWeaponIndex = 0; private static int lastTimeWeaponIndex = 0;
private static int lastTimeRenderWeaponIndex = 0; private static int lastTimeRenderWeaponIndex = 0;
private static final AnimationTimer weaponIndexUpdateTimer = new AnimationTimer(ANIMATION_TIME, AnimationCurves.EASE_OUT_CIRC); private static final AnimationTimer weaponIndexUpdateTimer = new AnimationTimer(ANIMATION_TIME).animation(AnimationCurves.EASE_OUT_CIRC);
@SubscribeEvent(priority = EventPriority.HIGH) @SubscribeEvent(priority = EventPriority.HIGH)

View file

@ -16,6 +16,7 @@ import com.atsuishio.superbwarfare.perk.AmmoPerk;
import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper; import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.*; import com.atsuishio.superbwarfare.tools.*;
import com.atsuishio.superbwarfare.tools.animation.AnimationCurves;
import net.minecraft.client.CameraType; import net.minecraft.client.CameraType;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
@ -1045,8 +1046,8 @@ public class ClientEventHandler {
} else { } else {
zoomTime = Mth.clamp(zoomTime - 0.04 * speed * times, 0, 1); zoomTime = Mth.clamp(zoomTime - 0.04 * speed * times, 0, 1);
} }
zoomPos = 0.5 * Math.cos(Math.PI * Math.pow(Math.pow(zoomTime, 2) - 1, 2)) + 0.5; zoomPos = AnimationCurves.EASE_IN_OUT_QUINT.apply(zoomTime);
zoomPosZ = -Math.pow(2 * zoomTime - 1, 2) + 1; zoomPosZ = AnimationCurves.PARABOLA.apply(zoomTime);
} }
private static void handleWeaponFire(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) { private static void handleWeaponFire(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) {

View file

@ -3,7 +3,15 @@ package com.atsuishio.superbwarfare.tools.animation;
import java.util.function.Function; import java.util.function.Function;
// https://easings.net/
public class AnimationCurves { public class AnimationCurves {
public static final Function<Float, Float> LINEAR = progress -> progress;
public static final Function<Float, Float> EASE_OUT_CIRC = progress -> (float) Math.sqrt(1 - Math.pow(progress - 1, 2)); public static final Function<Double, Double> LINEAR = x -> x;
public static final Function<Double, Double> EASE_OUT_CIRC = x -> Math.sqrt(1 - Math.pow(x - 1, 2));
public static final Function<Double, Double> EASE_IN_EXPO = x -> x == 0 ? 0 : Math.pow(2, 10 * x - 10);
public static final Function<Double, Double> EASE_OUT_EXPO = x -> x == 1 ? 1 : (1 - Math.pow(2, -10 * x));
public static final Function<Double, Double> EASE_IN_OUT_QUINT = x -> x < 0.5 ? 4 * x * x * x : (1 - Math.pow(-2 * x + 2, 3) / 2);
// wtf
public static final Function<Double, Double> PARABOLA = x -> -Math.pow(2 * x - 1, 2) + 1;
} }

View file

@ -11,26 +11,30 @@ public class AnimationTimer {
private boolean initialized; private boolean initialized;
private boolean isStart = true; private boolean isStart = true;
private final Function<Float, Float> animationCurve; private Function<Double, Double> forwardAnimationCurve = AnimationCurves.LINEAR;
private Function<Double, Double> backwardAnimationCurve = AnimationCurves.LINEAR;
/** /**
* 创建一个反向线性动画计时器 * 创建一个动画计时器
* *
* @param duration 动画持续时间单位为毫秒 * @param duration 动画持续时间单位为毫秒
*/ */
public AnimationTimer(long duration) { public AnimationTimer(long duration) {
this(duration, AnimationCurves.LINEAR); this.duration = duration;
} }
/** public AnimationTimer animation(Function<Double, Double> animationCurve) {
* 创建一个反向动画计时器 return this.forwardAnimation(animationCurve).backwardAnimation(animationCurve);
* }
* @param duration 动画持续时间单位为毫秒
* @param animationCurve 动画曲线函数 public AnimationTimer forwardAnimation(Function<Double, Double> animationCurve) {
*/ this.forwardAnimationCurve = animationCurve;
public AnimationTimer(long duration, Function<Float, Float> animationCurve) { return this;
this.duration = duration; }
this.animationCurve = animationCurve;
public AnimationTimer backwardAnimation(Function<Double, Double> animationCurve) {
this.backwardAnimationCurve = animationCurve;
return this;
} }
/** /**
@ -51,11 +55,23 @@ public class AnimationTimer {
* @param duration 动画持续时间单位为毫秒 * @param duration 动画持续时间单位为毫秒
* @param animationCurve 动画曲线函数 * @param animationCurve 动画曲线函数
*/ */
public static AnimationTimer[] createTimers(int size, long duration, Function<Float, Float> 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 timers = new AnimationTimer[size];
var currentTime = System.currentTimeMillis(); var currentTime = System.currentTimeMillis();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
timers[i] = new AnimationTimer(duration, animationCurve); timers[i] = new AnimationTimer(duration).forwardAnimation(forwardAnimationCurve).backwardAnimation(backwardAnimationCurve);
timers[i].end(); timers[i].end();
timers[i].backward(currentTime); timers[i].backward(currentTime);
} }
@ -74,9 +90,9 @@ public class AnimationTimer {
*/ */
public float getProgress(long currentTime) { public float getProgress(long currentTime) {
if (reversed) { if (reversed) {
return 1 - animationCurve.apply(Mth.clamp(1 - getElapsedTime(currentTime) / (float) duration, 0, 1)); return 1 - backwardAnimationCurve.apply(Mth.clamp(1 - getElapsedTime(currentTime) / (double) duration, 0, 1)).floatValue();
} else { } else {
return animationCurve.apply(Mth.clamp(getElapsedTime(currentTime) / (float) duration, 0, 1)); return forwardAnimationCurve.apply(Mth.clamp(getElapsedTime(currentTime) / (double) duration, 0, 1)).floatValue();
} }
} }