简体   繁体   中英

Java bouncing ball

I'm doing this bouncing ball problem and I have was given this formula: (velocity) vx = v0*cos(angle). and (x-position) x = v0*cos(angle)*t. However, I cannot get the ball to bounce properly. The problem is that after the ball hits the right vertical wall, it starts to bounce inside certain range on the right-hand-side of the window. (y and vy shouldn't matter in this case.) How can I fix this weird bouncing problem to make it bounce property in the x direction?

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();
    }
}

You're not even close. The differential equations of motion for a ball with gravity supplying the only force are

d^2x/dt^2 = -9.8  and d^2x/dt^2 = 0 

You need to integrate these equations. For this purpose, you need to get rid of the second degree differentials by introducing a new variable:

dv_y/dt = -9.8      and dv_x/dt = 0
dy/dt = v_y               dx/dt = v_x

With Euler forward differences (the simplest possible integration method), this becomes:

 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] 

When the ball encounters a vertical wall with a perfectly elastic collision, the x velocity instantly changes sign. When it hits the floor or ceiling, the y velocity changes sign.

Your formula provides only the initial values of v_x and v_y . All x and y values after are results of the above Euler equations. In pseudocode it will look something like this:

// 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
}

Note that that 9.8 means that the units are meters and seconds. You need to scale pixels in the Java window and use a timer to get a realistic result.

To roughly simulate lossy collision, you can steal some velocity on every bounce:

x = -<a number a bit less than 1.0> * x  and
y = -<a number a bit less than 1.0> * y

With these, the ball will slow down a bit every time it hits a wall.

I can't find where you're changing the angle after detecting a bounce. I also don't see bounds checking for all four sides of the windows the ball is in.

There's a related bug you might run into where there's a double bounce in a corner that leaves the ball outside the window after all the calculations are done. Think about ways to handle that case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM