Need to slow rectangle movement

381 Views Asked by At

I am having a problem with threading. I am trying to recreate pong where there are 2 Action Listeners for 2 players. The 2 paddles move at the speed that I want them to move at. However, the "ball"(Rectangle object with an oval painted over it) is moving way too fast. I've tried slowing it down using a second thread in the Ball class, but that doesn't seem to work. Any help would be appreciated. Here's my code:

public class BattleBallz extends JFrame implements Runnable {
AL keyListen1 = new AL();
AL2 keyListen2 = new AL2();
Image dbi;
Graphics dbg;

int x1,x2;
int ballX, ballY, direction;
Ball b1;

public BattleBallz(){
    setTitle("Battle Ballz");
    setSize(350, 400);
    setResizable(false);
    setVisible(true);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    addKeyListener(keyListen1);
    addKeyListener(keyListen2);
    x1 = 150;
    x2 = 150;
    int direction = 0 + (int)(Math.random() * ((2 - 0) + 1));
    b1 = new Ball(direction);
    Thread b = new Thread(b1);
    b.start();
}

public void paint(Graphics g){
    dbi = createImage(getWidth(), getHeight());
    dbg = dbi.getGraphics();
    paintComponent(dbg);
    g.drawImage(dbi, 0, 0, this);
}

public void paintComponent(Graphics g){
    Rectangle p1 = new Rectangle(x1,375,60,10);
    g.setColor(Color.blue);
    g.fillRect(x1, 375, 60, 10);
    Rectangle p2 = new Rectangle(x2,45,60,10);
    g.setColor(Color.red);
    g.fillRect(x2,45,60,10);

    b1.paintComponent(g, p1, p2);

    repaint();
}


@Override
public void run() {
    try {
        while(true){
            move();
            Thread.sleep(5);
        }
    } catch (Exception e) {
        // TODO: handle exception
    }

}

public void move(){
    x1 += keyListen1.getXdirection();
    x2 += keyListen2.getXdirection();

    if (x1<=0){
        x1 =0;
    }
    if (x1>=305){
        x1 = 305;
    }
    if (x2<=0){
        x2=0;
    }
    if (x2>=305){
        x2=305;
    }
}
}

public class Ball extends JPanel implements Runnable {

boolean up,down,right,left;
int x = 150, y = 150 ;

public Ball(int direction){
    if(direction ==1){
        down = true;
    }
    if (direction ==0){
        up = true;
    }
}

public void paintComponent(Graphics g, Rectangle p1, Rectangle p2){
    super.paintComponents(g);
    if(down){
        y++;
        Rectangle ball = new Rectangle(x,y,49,49);
        g.fillOval(x, y, 50, 50);
        if (y>=385 || ball.intersects(p1)){
            down = false;
            up = true;
        }
    }
    if (up){
        y--;
        Rectangle ball = new Rectangle(x,y,49,49);
        g.fillOval(x, y, 50, 50);
        if (y<=10 || ball.intersects(p2)){
            up = false;
            down = true;
        }
    }
}

@Override
public void run() {
    // TODO Auto-generated method stub
    try {
        while (true){
            Thread.sleep(30);
        }
    } catch (Exception e) {
        // TODO: handle exception
    }
}
}
1

There are 1 best solutions below

1
On
  1. use Swing Timer instead of plain Thread, you have an issue with Concurency in Swing, code posted to block Event Dispatch Thread, locked by Thread.sleep, endless block

  2. use paintComponent but put there JPanel, 1st. code line inside should be super.paintComponent, otherwise paint is cumulated, override getPreferredSize for JPanel

  3. use KeyBindings instead of KeyListener