在 java 中超时将一个值缓和到另一个值
Easing a value to another value overtime in java
我想缓和一个超时值,例如我有数字 85,我想根据一定的延迟缓和到 180 慢/快,这是一个直观的例子:
TIME: 0sec 0.25sec 0.5sec 0.75sec 1sec
VALUE: 85 100 126 140 180
我知道我需要的是 System.currentTimeMillis()
,但是我不知道如何正确使用它来确定下一毫秒的下一个值是什么
我正在尝试实现一种在 Minecraft 中偏航和俯仰的缓和方法,因此它不仅仅是即时的偏航和俯仰变化。
如果您需要任何其他信息,请随时询问。
我试过的代码:
public void easeValue(int delay) {
oldValue = (float) Math.ceil((System.currentTimeMillis() + delay) / oldValue);
if (oldValue >= targetValue) {
System.out.println("target reached");
}
}
(我不知道我在做什么)
System.cTM
的一个问题是它会随着时钟设置的变化而变化。这确实会发生——通常是服务器和计算机 运行 NTP 守护进程,它们会根据联网的时间服务器检查当前时间,并在需要时进行调整。通常,夏令时或切换时区不应该影响它,但是,好的 NTP 守护进程会抹去变化,这意味着你的缓动只会变慢或变快,而不是完全崩溃。
尽管如此,一种简单的解决方法是使用 System.nanoTime
而不是或多或少 'CPU uptime'(我过于简单化),并且不受任何时间守护进程或用户手动更改时间。
一个小问题是 nanoTime 可能会溢出,您需要考虑到这一点。
您的代码段没有考虑 'start point' 的任何概念。你不能写一个公式来计算你在从 85 到 180 的线性进展中的位置,除非你知道应该在什么时间点返回“85”,在什么时间点返回“180”。因此,该方法显然永远不会只是 ease(int delay)
。您需要将 'start and end' 数字(在您的示例中为 85 和 180)存储在某处,同样适用于开始和结束 time,需要将其转换为绝对数字在某个时刻(当您希望开始缓动时)。就是java,那就做java擅长的,做一个对象来表示这个状态吧
这是一个基本的想法:
import java.util.concurrent.TimeUnit;
public class Easing {
private final long duration; // in nanos
private final long startTime;
private final long endTime;
private final int startValue;
private final int endValue;
private Easing(long duration, int startValue, int endValue) {
if (duration < 1) throw new IllegalArgumentException("duration not positive");
this.duration = duration;
this.startTime = System.nanoTime();
this.endTime = this.start + duration;
this.startValue = startValue;
this.endValue = endValue;
}
public static Easing ofSeconds(int seconds, int startValue, int endValue) {
return new Easing(TimeUnit.SECONDS.toNanos(seconds), startValue, endValue);
}
public int getCurrentValue() {
long now = System.nanoTime();
long delta = now - startTime;
long range = endTime - startTime;
if (delta > range) return endValue;
double p = 1.0 * delta / range;
int valRange = endValue - startValue;
return (int) (0.5 + (p * valRange) + startValue);
}
}
让我们看看实际效果:
public static void main(String[] args) throws Exception {
Easing easing = Easing.ofSeconds(10, 80, 180);
long start = System.currentTimeMillis();
for (int i = 0; i < 55; i++) {
long mark = System.currentTimeMillis();
System.out.printf("At [%d]: %d\n", mark - start, easing.getCurrentValue());
Thread.sleep(200);
}
}
At [0]: 80
At [229]: 82
At [430]: 84
At [633]: 86
At [839]: 88
At [1042]: 90
At [1244]: 92
At [1448]: 94
At [1651]: 97
At [1856]: 99
At [2060]: 101
At [2265]: 103
At [2468]: 105
At [2673]: 107
At [2878]: 109
At [3080]: 111
At [3284]: 113
At [3489]: 115
At [3693]: 117
At [3897]: 119
At [4101]: 121
At [4306]: 123
At [4510]: 125
At [4715]: 127
At [4919]: 129
At [5125]: 131
At [5329]: 133
At [5531]: 135
At [5735]: 137
At [5937]: 139
At [6139]: 141
At [6342]: 143
At [6544]: 145
At [6749]: 147
At [6952]: 150
At [7156]: 152
At [7361]: 154
At [7565]: 156
At [7770]: 158
At [7975]: 160
At [8178]: 162
At [8380]: 164
At [8581]: 166
At [8785]: 168
At [8986]: 170
At [9188]: 172
At [9392]: 174
At [9595]: 176
At [9797]: 178
At [10002]: 180
At [10207]: 180
At [10411]: 180
At [10613]: 180
At [10814]: 180
At [11019]: 180
我想缓和一个超时值,例如我有数字 85,我想根据一定的延迟缓和到 180 慢/快,这是一个直观的例子:
TIME: 0sec 0.25sec 0.5sec 0.75sec 1sec
VALUE: 85 100 126 140 180
我知道我需要的是 System.currentTimeMillis()
,但是我不知道如何正确使用它来确定下一毫秒的下一个值是什么
我正在尝试实现一种在 Minecraft 中偏航和俯仰的缓和方法,因此它不仅仅是即时的偏航和俯仰变化。
如果您需要任何其他信息,请随时询问。
我试过的代码:
public void easeValue(int delay) {
oldValue = (float) Math.ceil((System.currentTimeMillis() + delay) / oldValue);
if (oldValue >= targetValue) {
System.out.println("target reached");
}
}
(我不知道我在做什么)
System.cTM
的一个问题是它会随着时钟设置的变化而变化。这确实会发生——通常是服务器和计算机 运行 NTP 守护进程,它们会根据联网的时间服务器检查当前时间,并在需要时进行调整。通常,夏令时或切换时区不应该影响它,但是,好的 NTP 守护进程会抹去变化,这意味着你的缓动只会变慢或变快,而不是完全崩溃。
尽管如此,一种简单的解决方法是使用 System.nanoTime
而不是或多或少 'CPU uptime'(我过于简单化),并且不受任何时间守护进程或用户手动更改时间。
一个小问题是 nanoTime 可能会溢出,您需要考虑到这一点。
您的代码段没有考虑 'start point' 的任何概念。你不能写一个公式来计算你在从 85 到 180 的线性进展中的位置,除非你知道应该在什么时间点返回“85”,在什么时间点返回“180”。因此,该方法显然永远不会只是 ease(int delay)
。您需要将 'start and end' 数字(在您的示例中为 85 和 180)存储在某处,同样适用于开始和结束 time,需要将其转换为绝对数字在某个时刻(当您希望开始缓动时)。就是java,那就做java擅长的,做一个对象来表示这个状态吧
这是一个基本的想法:
import java.util.concurrent.TimeUnit;
public class Easing {
private final long duration; // in nanos
private final long startTime;
private final long endTime;
private final int startValue;
private final int endValue;
private Easing(long duration, int startValue, int endValue) {
if (duration < 1) throw new IllegalArgumentException("duration not positive");
this.duration = duration;
this.startTime = System.nanoTime();
this.endTime = this.start + duration;
this.startValue = startValue;
this.endValue = endValue;
}
public static Easing ofSeconds(int seconds, int startValue, int endValue) {
return new Easing(TimeUnit.SECONDS.toNanos(seconds), startValue, endValue);
}
public int getCurrentValue() {
long now = System.nanoTime();
long delta = now - startTime;
long range = endTime - startTime;
if (delta > range) return endValue;
double p = 1.0 * delta / range;
int valRange = endValue - startValue;
return (int) (0.5 + (p * valRange) + startValue);
}
}
让我们看看实际效果:
public static void main(String[] args) throws Exception {
Easing easing = Easing.ofSeconds(10, 80, 180);
long start = System.currentTimeMillis();
for (int i = 0; i < 55; i++) {
long mark = System.currentTimeMillis();
System.out.printf("At [%d]: %d\n", mark - start, easing.getCurrentValue());
Thread.sleep(200);
}
}
At [0]: 80
At [229]: 82
At [430]: 84
At [633]: 86
At [839]: 88
At [1042]: 90
At [1244]: 92
At [1448]: 94
At [1651]: 97
At [1856]: 99
At [2060]: 101
At [2265]: 103
At [2468]: 105
At [2673]: 107
At [2878]: 109
At [3080]: 111
At [3284]: 113
At [3489]: 115
At [3693]: 117
At [3897]: 119
At [4101]: 121
At [4306]: 123
At [4510]: 125
At [4715]: 127
At [4919]: 129
At [5125]: 131
At [5329]: 133
At [5531]: 135
At [5735]: 137
At [5937]: 139
At [6139]: 141
At [6342]: 143
At [6544]: 145
At [6749]: 147
At [6952]: 150
At [7156]: 152
At [7361]: 154
At [7565]: 156
At [7770]: 158
At [7975]: 160
At [8178]: 162
At [8380]: 164
At [8581]: 166
At [8785]: 168
At [8986]: 170
At [9188]: 172
At [9392]: 174
At [9595]: 176
At [9797]: 178
At [10002]: 180
At [10207]: 180
At [10411]: 180
At [10613]: 180
At [10814]: 180
At [11019]: 180