我的Java弹跳球以较大的速度弹跳起来



我正在编写一个简单的Java程序来上下弹球。问题是每次球反弹的高度都高于它的起始点。我希望球能反弹到它开始时的高度。

球物理可以在dphysics()方法中的圆圈类中找到,我怀疑可以找到问题

import java.awt.*;
import java.util.*;
public class Main{

public static Frame frame = new Frame();
public static Physics physics = new Physics();
public static ArrayList<Circle> circles = new ArrayList<Circle>(); //array for the points
public static void main(String args[]) {
Circle circle = new Circle(100, 300, 50, Color.BLACK);
circles.add(circle);

run();
}

public static void run() {
physics.timer.start();
}
}
import java.awt.*;
public class Circle {

private int x;
private int y;

private double xAccel= 0;
private double yAccel = 0;

private double xVel= 0;
private double yVel = 0;

private Color colour;
private int radius;

public Circle(int x, int y, int radius, Color colour) {
setX(x);
setY(y);
setRadius(radius);
setColour(colour);
}

public void draw(Graphics2D g2d) {
g2d.setColor(colour);
g2d.fillOval(x, y, radius*2, radius*2);
}

public void doPhysics() {
hitGround();
System.out.println(yVel);

yVel += Physics.getGravity();
y -= yVel;
}

public void hitGround() {
if(y + radius*2 > Frame.panel.h ) {
yVel = -yVel;
}
}

public void setX(int x) {
this.x = x;
}

public void setY(int y) {
this.y = y;
}

public void setColour(Color colour) {
this.colour = colour;
}

public void setRadius(int radius) {
this.radius = radius;
}

public int getX() {
return x;
}

public int getY() {
return y;
}

public Color getColour() {
return colour;
}

public int getRadius() {
return radius;
}
}
import java.awt.*;
import javax.swing.*;
class Frame extends JFrame {

public static Panel panel;
public Frame() {
panel = new Panel();
this.setTitle("Fun");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
class Panel extends JPanel {

public int w = 500;
public int h = 500;

public Panel() {
this.setPreferredSize(new Dimension(w, h));
this.setBackground(Color.red);
}

public void paint(Graphics g) {
super.paint(g);

Graphics2D g2d = (Graphics2D) g;

for(Circle circle : Main.circles) {
circle.draw(g2d);
}
}

}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Physics implements ActionListener {

private static double gravity = -.1;
public Timer timer;

public Physics() {
timer = new Timer(1, this);
}

public static double getGravity() {
return gravity;
}
@Override
public void actionPerformed(ActionEvent e) {
for(Circle circle : Main.circles) {
circle.doPhysics();
}
Main.frame.repaint();
}

}

问题主要是由于位置(xy)使用整数值引起的。在每次迭代中,值被舍入,错误被累积。
解决方案:声明double xdouble y,只使用四舍五入的整数值绘图。

以上可以减少问题,但不能完全解决问题。随着时间的推移,代码正在进行粗略的集成¹通过使用时间间隔后计算的速度(参见数值积分)。这可以通过对改变前后的速度进行平均来改进。约:

double preVel = yVel;
yVel += Physics.getGravity(); 
y -= (preVel + yVel)/2;

可以简化(纯数学)为:

yVel += Physics.getGravity();
y -= yVel - Physics.getGravity()/2;

这应该工作良好,因为加速度是恒定的。如果加速度也在变化,情况就不一样了。而且随着时间的推移,它也容易受到精度误差的影响。

1

-参见数值积分和时间离散

最新更新