2
\$\begingroup\$

I've taken up the challenge of creating a basic 2D side-scrolling monster truck game for my little brother. It seems easy enough in theory, but jumping into Java out of XNA feels strange.

My game class has a private class GameLoop extending Runnable. In the overridden run() method, a while-loop handles time and such. There's a targetFPS for drawing as well. The loop looks like this:

public void run()
{
    long fpsTime = 0;

    gameStart = System.currentTimeMillis();
    lastTime = System.currentTimeMillis();

    while(game.isGameRunning())
    {
        currentTime = System.currentTimeMillis();

        long ellapsedTime = currentTime - lastTime;

        if(mouseState.leftIsDown)
        {
            que.add(new Dot(mouseState.getPosition()));
        }

        entities.addAll(que);

        game.updateGame(ellapsedTime);

        fpsTime += ellapsedTime;
        if(fpsTime >= (1000 / targetedFPS))
        {
            game.drawGame(ellapsedTime);
        }

        lastTime = currentTime;
    }

I'm running into a problem when adding entities after a click. I made a class with a private class extending MouseListener and MouseMotionListener, then on changes I have it set a few booleans to tell me if the mouse is pressed or not which seems to work great. However, when I add the entity, I occasionally get a CME (Concurrent Modification Exception). All the entities are stored in a LinkedList<Entity>.

I also tried adding a queued LinkedList, where I add the contents of the queue to the normal list later in the update loop.

I think this would work fine if it was just the update method in the game loop, but it's the repaint() method (called from game.drawGame()) that throws the CME.

The only other thing is that I'm currently drawing directly from the overridden paintComponent() method in a custom class extending JPanel.

Is a better way to go about this? How do I fix the CME?

\$\endgroup\$
2
  • \$\begingroup\$ My guess is that the issue is caused by using "for (int i = 0; i < ...; i++)" loops over iterators. Generally speaking most people seem to prefer the standard for loop but if you are modifying data (like removing an entry) you will get CME exceptions. Try changing your loop logic to something like the answer in this stackoverflow post: stackoverflow.com/questions/4097217/… \$\endgroup\$ Aug 15, 2013 at 16:44
  • \$\begingroup\$ Swing will redraw on its own thread, so if it is redrawing while you are adding entities from your game thread, you can get this exception. \$\endgroup\$
    – Terje
    Mar 13, 2014 at 12:26

2 Answers 2

1
\$\begingroup\$

If you're modifying a LinkedList on one thread (game loop thread), and iterating through it on another thread (the EDT, which is drawing your game), then you'll get the ConcurrentModificationException.

If you know you'll add new elements rarely, you can try to use a CopyOnWriteArrayList which is immune to ConcurrentModificationExceptions, but comes with some disadvantages. Also try using the addAll method once at the end of the game loop against a collection of new entities to add to the list.

\$\endgroup\$
0
\$\begingroup\$

I don't quite understand why you would face a ConcurrentModificationException being thrown unless you're doing bad iterator logic or adding/removing from a collection in one thread while you are iterating the collection in another.

It isn't an uncommon practice to have a pending list where entities that are being added and/or removed from the scene are referenced and at a stage in the game loop where concurrency isn't an issue, the master entity list gets updated by adding the new entities and those being removed are deleted.

I generally handle updating the entity list once I receive a FrameEnd event. At this point in my game engine, all data has been rendered, buffers swapped and I'm about to start a new frame.

\$\endgroup\$
2
  • \$\begingroup\$ I have to agree it does seem strange... I'm not exactly sure where my problem is to be truthful. I'm updating the list every time it loops, so this error really does not make sense. I was thinking maybe that the repaint() method runs on the EDT causing my game loop to loop back while the panel is still trying to iterate through the list being added to. Is that a possibility? Thank you so much for your response! \$\endgroup\$
    – Lost_Soul
    Jul 16, 2013 at 6:05
  • \$\begingroup\$ Iterators become invalid if you add or remove elements of a list from within a loop. \$\endgroup\$
    – Evan
    Sep 14, 2013 at 14:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .