2016-12-06 128 views
0

我正在做弹跳球问题,我给出了这个公式:(velocity)vx = v0 * cos(angle)。和(x位置)x = v0 * cos(角度)* t。但是,我无法让球正常弹跳。 问题是,当球击中右侧垂直墙后,它会在窗口右侧的某个范围内开始反弹。 (y和vy在这种情况下应该没有关系)。 我该如何解决这个奇怪的弹跳问题,使其在x方向上反弹属性?Java弹跳球

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_xv_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 

有了这些,球会有点每次撞墙时间慢下来。