2016-12-06 129 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 

有了這些,球會有點每次撞牆時間慢下來。