Java弹跳球

时间:2016-12-06 06:31:41

标签: java

我正在做这个弹跳球问题,我得到了这个公式:(速度)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();
    }
}

2 个答案:

答案 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

有了这些,每次撞到墙壁时球都会减速。

答案 1 :(得分:0)

在检测到弹跳后,我找不到你改变角度的位置。我也没有看到边界检查球所在的窗户的所有四边。

你可能会遇到一个相关的错误,在完成所有计算后,在角落里有一次双反弹,将球留在窗外。想一想处理这种情况的方法。