2

I'm trying to make a Brick Breaker game, but I'm getting a ConcurrentModificationException in this area.
I use Netbeans. This is in my BlockBreakerPanel class and it has the main information for getting my code to actually work properly. Exception location has ** around it.
I don't know why I get this exception and I'm wondering if it has to do with the Arraylist and if I somehow implemented it wrong.

public class BlockBreakerPanel extends JPanel implements KeyListener {

ArrayList<Block> blocks;
Block ball;
Block paddle;

JFrame mainFrame, startScreen;

Thread thread;

void reset() {
    blocks = new ArrayList<Block>();
    ball = new Block(237, 435, 35, 25, "ball.png");
    paddle = new Block(175, 480, 150, 25, "paddle.png");
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 0, 60, 25, "blue.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 25, 60, 25, "green.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 50, 60, 25, "yellow.png"));
    }
    for (int i = 0; i < 8; i++) {
        blocks.add(new Block((i * 60 + 2), 75, 60, 25, "red.png"));
    }

    addKeyListener(this);
    setFocusable(true);
}

BlockBreakerPanel(JFrame frame, JFrame startScreen) {

    this.mainFrame = frame;
    this.startScreen = startScreen;

    reset();

    thread = new Thread(() -> {
        while (true) {
            update();
            try {
                Thread.sleep(10);
            } catch (InterruptedException err) {
                err.printStackTrace();
            }
        }
    });
    thread.start();

}
**public void paintComponent(Graphics g) {
    super.paintComponent(g);
    blocks.forEach(block -> {
        block.draw(g, this);
    });
    ball.draw(g, this);
    paddle.draw(g, this);
}**
public void update() {
    ball.x += ball.movX;
    
    if (ball.x > (getWidth() - 25) || ball.x < 0) {
        ball.movX *= -1;
    }

    if (ball.y < 0 || ball.intersects(paddle)) {
        ball.movY *= -1;
    }

    ball.y += ball.movY;

    if (ball.y > getHeight()) {
        thread = null;
        reset();
        mainFrame.setVisible(false);
        startScreen.setVisible(true);

    }
    blocks.forEach(block -> {
        if (ball.intersects(block) && !block.destroyed) {
            block.destroyed = true;
            ball.movY *= -1;
        }
    });
    repaint();

}

@Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyPressed(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_RIGHT && paddle.x < (getWidth() - paddle.width)) {
        paddle.x += 15;
    }

    if (e.getKeyCode() == KeyEvent.VK_LEFT && paddle.x > 0) {
        paddle.x -= 15;
    }

}

@Override
public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

}

}

fantaghirocco
  • 4,761
  • 6
  • 38
  • 48
joeyipod
  • 81
  • 8
  • 1
    What is `blocks` and where do you update it? – luk2302 Dec 28 '20 at 19:59
  • `blocks` is an arraylist I made that contains various PNG images that make the blocks. `blocks = new ArrayList();` – joeyipod Dec 28 '20 at 20:02
  • No sadly it doesn't @luk2302. I wish it did. I need a fix to the code, and what it should look like compared to what I have. – joeyipod Dec 28 '20 at 20:20
  • which line of code is the exception coming from? what is the full stack trace? – jtahlborn Dec 28 '20 at 20:35
  • Yes, it *does* answer the question in the sense that it covers what the exception is, why it arises and how to prevent it. – luk2302 Dec 28 '20 at 20:35
  • @luk2302 - except that nothing in this code that i can see removes anything from the `blocks` list? – jtahlborn Dec 28 '20 at 20:41
  • i re-opened this question. while ConcurrentModificationException does have lots of helpful answers already on SO, the relevance/application to _this_ question is not immediately obvious at this time. – jtahlborn Jan 04 '21 at 16:35

1 Answers1

1

I suspect that the crux of your problem is that you are using a separate thread to interact with GUI elements. That is a no-no in Java, the AWT/Swing UI elements are not thread-safe. You must do all UI interactions on the event dispatch thread. Generally, this is very straightforward for normal interactive situations. In your case, however, you need a UI task to happen periodically. When you need a periodic update to UI elements in Java, you should use a swing timer. This will ensure that your updates happen in a UI thread-safe manner.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • So what edits do I need to make to the code in this class specifically for it to work? What do I need to add in what specific methods? – joeyipod Dec 28 '20 at 22:40
  • 1
    @joey did you read through all the links i provided? you need to stop using a thread and start using a swing timer – jtahlborn Jan 04 '21 at 16:32