如何将 Java 计时器实时关联到毫秒,并相应地更新时间变量?
How can I relate the Java Timer to milliseconds in real time, and update a time variable accordingly?
我一直在做一些关于射弹运动的代码。我启动了一个计时器 t 并为其使用了构造函数 10,每个动作事件我将 0.01 添加到初始化为 0.00 的时间变量中,以模拟时间过去。使用这次我计算 height/distance 等。我无法弄清楚 2 个问题:
1) 将当前时间打印到控制台时,它会一直转到许多小数位,运行 代码。
2) 本来不该长高的,还是会长长的,我感觉是加速度的正负关系。
(我的面板是 1920x1080,面板动画占用 80 像素 - 这就是为什么它是 1000-50)(1000 半径)
来自回复:
1) 忘记将 vy 乘以 t。
2) 使用 DecimalFormat 来 t运行 计算值
感谢@G_H; @砖块; @汤姆; @Diginoise
代码:
package projectV1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Animate extends JPanel implements ActionListener {
double x = 0;
double time = 0.00;
String timeText2 = "0";
double y = 1000;
double velY = 0.0;
double velX = 0.0;
public static Timer t;
public Animate() { // Constructor
super();
}
public void start(String acceleration, String initialVelocity, String angle){
new Ball(acceleration, angle, initialVelocity);
t = new Timer(10, this);
t.start();
}
@Override
public void actionPerformed(ActionEvent e) {
updateTime();
move();
}
public void move(){ // HOlds the repaint method
x = x + Ball.getVelX();
Simulation.distanceText.setText(Double.toString(Ball.getDistance(time))); // Some of these are just checks for me in the gui
Simulation.velocityText.setText(Double.toString(time));
y = y- Ball.getVelY(time);
Simulation.heightText.setText(Double.toString(Ball.getHeight(time)));
repaint();
}
public void updateTime(){
time= time + 0.01;
System.out.println(Double.toString(time)); // Using this as a test to check the time output.
timeText2 = Double.toString(time);
Simulation.timeText.setText(timeText2);
}
public void paintComponent(Graphics gg){
super.paintComponent(gg);
gg.drawRect(0, 0, 1920, 1000);
Graphics2D g = (Graphics2D) gg;
Ellipse2D.Double shape = new Ellipse2D.Double(x, y-50.0, 50, 50);
g.fill(shape);
// g.fillOval(x, y-50, 50, 50);
}
}
来自“球Class”的代码
public Ball(String acceleration, String angle, String initialVelocity ) {
Ball.acceleration = acceleration;
Ball.initialVelocity = initialVelocity;
Ball.angle = angle;
}
public static double getVelX(){ // This stays constant throughout the program
double velX = 0.0;
int u = Integer.parseInt(initialVelocity);
double ang = Double.parseDouble(angle);
velX = u*(Math.cos(ang));
return velX;
}
public static double getVelY(double time ){
double velY = 0.0 ;
double ang, acc = 0;
int u = 0;
ang = Double.parseDouble(angle);
acc = Double.parseDouble(acceleration);
u = Integer.parseInt(initialVelocity);
velY = u*(Math.sin(ang))- (acc*time);
return velY;
}
public static double getDistance(double time){
double distance = 0;
double ang = 0;
int u = 0;
ang = Double.parseDouble(angle);
u = Integer.parseInt(initialVelocity);
distance = (u*time)*(Math.cos(ang));
return distance;
}
public static double predictedTime(){
double ptime = 0;
double ang = 0;
ang = Double.parseDouble(angle);
int u = Integer.parseInt(initialVelocity);
ptime = ((u*u)*(Math.sin(ang)*Math.sin(ang))/(2*9.81));
return ptime;
}
public static double getHeight(double time ){
double height;
double ang, acc;
int u = 0;
ang = Double.parseDouble(angle);
acc = Double.parseDouble(acceleration);
u = Integer.parseInt(initialVelocity);
height = u*(Math.sin(ang))-(0.5*acc*(time*time));
return height;
}
1) When printing the current time into the console it keeps going to many decimal places, run code.
这是由于小数的二进制表示。假设我们尝试用十进制表示 1/3,您会得到 0.333333... 扩展是无限的,没有有限表示。 0.01 (1/100) 有有限的十进制表示,但不是二进制。所以如果你写 double d = 0.01;
,就知道内部二进制表示是一个近似值,而不是精确值。您需要将输出截断为具有特定小数位数的某个值。查看 class DecimalFormat 以特定格式输出值。
2) Height will keep increasing even though it shouldn't, I feel as if it is due to the positive and negative of acceleration.
检查这部分:velY = u*(Math.sin(ang))- (acc*time);
u
是一个常量。 sin(ang)
也是。 acc*time
只会增加。所以 velY 将线性变化是有道理的。您发布了这个:
它表示 Sy = Vy*t - 0.5*g*t²
,然后是 Vy = u*sin(ang)
。等式的扩展中缺少时间分量。应该是这样的:velY = (u*(Math.sin(ang))- (acc*time)) * time;
或者(理论上是一样的)velY = u*(Math.sin(ang))*time - (acc*time*time);
注意 acc
必须是 1/2 g。如果您提供 g 作为加速度,则需要根据 formula for vertical displacement.
将 acc*time*time
乘以 0.5
最后要注意的是,你把各种字段变成了class Ball 的静态字段,然后在构造函数中分配它们。最好不要那样做。使 Ball 的字段 acceleration
、initialVelocity
和 angle
instance 字段(它们可以是最终的,因为它们不会改变)并使方法非-静态的。这将允许您模拟多个球,例如,因为它们的值对它们保持本地状态,而不是共享 class 状态。
我一直在做一些关于射弹运动的代码。我启动了一个计时器 t 并为其使用了构造函数 10,每个动作事件我将 0.01 添加到初始化为 0.00 的时间变量中,以模拟时间过去。使用这次我计算 height/distance 等。我无法弄清楚 2 个问题:
1) 将当前时间打印到控制台时,它会一直转到许多小数位,运行 代码。 2) 本来不该长高的,还是会长长的,我感觉是加速度的正负关系。
(我的面板是 1920x1080,面板动画占用 80 像素 - 这就是为什么它是 1000-50)(1000 半径)
来自回复: 1) 忘记将 vy 乘以 t。 2) 使用 DecimalFormat 来 t运行 计算值
感谢@G_H; @砖块; @汤姆; @Diginoise 代码:
package projectV1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Animate extends JPanel implements ActionListener {
double x = 0;
double time = 0.00;
String timeText2 = "0";
double y = 1000;
double velY = 0.0;
double velX = 0.0;
public static Timer t;
public Animate() { // Constructor
super();
}
public void start(String acceleration, String initialVelocity, String angle){
new Ball(acceleration, angle, initialVelocity);
t = new Timer(10, this);
t.start();
}
@Override
public void actionPerformed(ActionEvent e) {
updateTime();
move();
}
public void move(){ // HOlds the repaint method
x = x + Ball.getVelX();
Simulation.distanceText.setText(Double.toString(Ball.getDistance(time))); // Some of these are just checks for me in the gui
Simulation.velocityText.setText(Double.toString(time));
y = y- Ball.getVelY(time);
Simulation.heightText.setText(Double.toString(Ball.getHeight(time)));
repaint();
}
public void updateTime(){
time= time + 0.01;
System.out.println(Double.toString(time)); // Using this as a test to check the time output.
timeText2 = Double.toString(time);
Simulation.timeText.setText(timeText2);
}
public void paintComponent(Graphics gg){
super.paintComponent(gg);
gg.drawRect(0, 0, 1920, 1000);
Graphics2D g = (Graphics2D) gg;
Ellipse2D.Double shape = new Ellipse2D.Double(x, y-50.0, 50, 50);
g.fill(shape);
// g.fillOval(x, y-50, 50, 50);
}
}
来自“球Class”的代码
public Ball(String acceleration, String angle, String initialVelocity ) {
Ball.acceleration = acceleration;
Ball.initialVelocity = initialVelocity;
Ball.angle = angle;
}
public static double getVelX(){ // This stays constant throughout the program
double velX = 0.0;
int u = Integer.parseInt(initialVelocity);
double ang = Double.parseDouble(angle);
velX = u*(Math.cos(ang));
return velX;
}
public static double getVelY(double time ){
double velY = 0.0 ;
double ang, acc = 0;
int u = 0;
ang = Double.parseDouble(angle);
acc = Double.parseDouble(acceleration);
u = Integer.parseInt(initialVelocity);
velY = u*(Math.sin(ang))- (acc*time);
return velY;
}
public static double getDistance(double time){
double distance = 0;
double ang = 0;
int u = 0;
ang = Double.parseDouble(angle);
u = Integer.parseInt(initialVelocity);
distance = (u*time)*(Math.cos(ang));
return distance;
}
public static double predictedTime(){
double ptime = 0;
double ang = 0;
ang = Double.parseDouble(angle);
int u = Integer.parseInt(initialVelocity);
ptime = ((u*u)*(Math.sin(ang)*Math.sin(ang))/(2*9.81));
return ptime;
}
public static double getHeight(double time ){
double height;
double ang, acc;
int u = 0;
ang = Double.parseDouble(angle);
acc = Double.parseDouble(acceleration);
u = Integer.parseInt(initialVelocity);
height = u*(Math.sin(ang))-(0.5*acc*(time*time));
return height;
}
1) When printing the current time into the console it keeps going to many decimal places, run code.
这是由于小数的二进制表示。假设我们尝试用十进制表示 1/3,您会得到 0.333333... 扩展是无限的,没有有限表示。 0.01 (1/100) 有有限的十进制表示,但不是二进制。所以如果你写 double d = 0.01;
,就知道内部二进制表示是一个近似值,而不是精确值。您需要将输出截断为具有特定小数位数的某个值。查看 class DecimalFormat 以特定格式输出值。
2) Height will keep increasing even though it shouldn't, I feel as if it is due to the positive and negative of acceleration.
检查这部分:velY = u*(Math.sin(ang))- (acc*time);
u
是一个常量。 sin(ang)
也是。 acc*time
只会增加。所以 velY 将线性变化是有道理的。您发布了这个:
它表示 Sy = Vy*t - 0.5*g*t²
,然后是 Vy = u*sin(ang)
。等式的扩展中缺少时间分量。应该是这样的:velY = (u*(Math.sin(ang))- (acc*time)) * time;
或者(理论上是一样的)velY = u*(Math.sin(ang))*time - (acc*time*time);
注意 acc
必须是 1/2 g。如果您提供 g 作为加速度,则需要根据 formula for vertical displacement.
acc*time*time
乘以 0.5
最后要注意的是,你把各种字段变成了class Ball 的静态字段,然后在构造函数中分配它们。最好不要那样做。使 Ball 的字段 acceleration
、initialVelocity
和 angle
instance 字段(它们可以是最终的,因为它们不会改变)并使方法非-静态的。这将允许您模拟多个球,例如,因为它们的值对它们保持本地状态,而不是共享 class 状态。