我正在做这个弹跳球问题,我得到了这个公式:(速度)vx = v0 * cos(角度)。和(x位置)x = v0 * cos(角度)* t。但是,我无法让球正常反弹。 问题是球击中右侧垂直墙后,它开始在窗口右侧的某个范围内反弹。 (在这种情况下,y和vy无关紧要。) 如何解决这个奇怪的弹跳问题,使其在x方向上反弹属性?
public class GamePanel2 extends JPanel implements KeyListener, ActionListener{
Timer tm = new Timer(60, this); //this refers to the ActionListener
public int score = 0;
public GamePanel2(){
addKeyListener(this);
setFocusable(true);
setBackground(Color.BLACK);
}
public int getScore() {
return score;
}
public double v0 = 100;
public double t = 0;
public double angle = Math.PI/2.5;
public double x = 0;
public double y = 0;
public double vx =0;
public double vy = 0;
public int move = 0;
public int paddlex =0;
public void paintComponent(Graphics g){
int h = getHeight();
int w = getWidth();
vx = v0*Math.cos(angle);
vy = v0*Math.sin(angle);
Graphics2D g2d = (Graphics2D)g;
g2d.translate(0.0,h);
g2d.scale(1.0, -1.0);
//ball
g2d.setColor(Color.GREEN);
g2d.fillOval((int)Math.round(x), (int)Math.round(y+6), 20, 20);
//paddle
g2d.setColor(Color.RED);
g2d.fillRect(paddlex + move, 0, 60, 6);
repaint();
}
//KeyListener methods
@Override
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_SPACE){
tm.start();
}
else if(arg0.getKeyCode()==KeyEvent.VK_ESCAPE){
tm.stop();
}
if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){
move += 30;
}
//if pressed right key
if(arg0.getKeyCode() == KeyEvent.VK_LEFT){
move -= 30;
}
repaint();
}
@Override
public void keyReleased(KeyEvent arg0) {
}
@Override
public void keyTyped(KeyEvent arg0) {
}
@Override
public void actionPerformed(ActionEvent arg0) {
t = 0.2;
vy -= 9.8;
x += vx;
y += (vy)*t-(t*t*9.8)*0.5;
if( x<= 0){
vx = v0*Math.cos(angle);
}
if (x>=getWidth()-20){
vx =-(v0*Math.cos(angle));
}
repaint();
}
}
答案 0 :(得分:1)
你甚至都没有关闭。具有重力供给唯一力的球的运动微分方程是
d^2x/dt^2 = -9.8 and d^2x/dt^2 = 0
您需要整合这些方程式。为此,您需要通过引入一个新变量来消除二度差异:
dv_y/dt = -9.8 and dv_x/dt = 0
dy/dt = v_y dx/dt = v_x
随着欧拉前向差异(最简单的积分方法),这变为:
v_y[i+i] = v_y[i] + h * -9.8
y[i+1] = y[i] + h * v_y[i]
v_x[i+1] = v_x[i] + h * 0 // x-velocity is constant!
x[i+1] = x[i] + h * v_x[i]
当球遇到具有完全弹性碰撞的垂直墙时,x速度立即改变符号。当它撞到地板或天花板时,y速度会改变符号。
您的公式仅提供v_x
和v_y
的初始值。之后的所有x和y值都是上述欧拉方程的结果。在伪代码中,它看起来像这样:
// Initialize the velocity components.
vx = v0 * cos(theta)
vy = v0 * sin(theta)
// Initialize the position of the ball.
x = R // in the corner of the first quadrant
y = R
// Choose a time increment.
h = < a very small number of seconds >
// Start the clock.
t = 0
while (t < END_OF_SIMULATION) {
draw_ball(x,y)
x = x + h * vx;
y = y + h * vy;
vy = vy - h * 9.8;
// Check for bounces
// Assumes box has corners (0,0), (W,H)
if ((vx < 0 and x < r) or (vx > 0 && x > W-r)) x = -x;
if ((vy < 0 and y < r) or (vy > 0 && y > H-r)) y = -y;
t = t + h
}
请注意,9.8表示单位为米和秒。您需要在Java窗口中缩放像素并使用计时器来获得逼真的结果。
要大致模拟有损碰撞,你可以在每次弹跳时偷取一些速度:
x = -<a number a bit less than 1.0> * x and
y = -<a number a bit less than 1.0> * y
有了这些,每次撞到墙壁时球都会减速。
答案 1 :(得分:0)
在检测到弹跳后,我找不到你改变角度的位置。我也没有看到边界检查球所在的窗户的所有四边。
你可能会遇到一个相关的错误,在完成所有计算后,在角落里有一次双反弹,将球留在窗外。想一想处理这种情况的方法。