0

Javaで簡単なゲームを書いています。メインコードは次のとおりです。

public class MainPanel extends JPanel {
    private Player player = new Player(100, 100, 3, 3);
    private Point2D targetPoint = new Point2D.Float(130, 350); //Pos on begin
    private ArrayList<Beam> beams = new ArrayList<Beam>();

    public MainPanel() {
        setPreferredSize(new Dimension(300, 400));

        addMouseMotionListener(new MouseMotionHandler());
        //Add shortcuts
        makeShortcut("player.BM1", "F1", new SetBeamModeAction(1));
        makeShortcut("player.BM2", "F2", new SetBeamModeAction(2));

        //Start threads
        Thread t = new Thread(new PlayerMoveRunnable());
        t.start();
        Thread t2 = new Thread(new PlayerShootRunnable());
        t2.start();
    }

    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(Color.BLACK);
        g2.fillRect(0, 0, 300, 400);
        //Draw player
        g2.drawImage(player.getImage(), (int)player.getX(), (int)player.getY(), null);
        //Draw beams
        for (Beam beam : beams) {
            g2.drawImage(beam.getImage(), (int)beam.getX(), (int)beam.getY(), null);
        }
    }

    //Thread running all the time
    private class PlayerMoveRunnable implements Runnable {
        public void run() {
            try {
                while (true) {
                    player.moveToPoint(targetPoint);
                    repaint();
                    Thread.sleep(15);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //Thread working all the time
    private class PlayerShootRunnable implements Runnable {
        public void run() {
            try {
                while (true) {
                    //Choose which beam to shoot (depends on set mode)
                    Thread t;
                    switch (player.getBeamMode()) {
                        case 1:
                            t = new Thread(new BeamMoveRunnable(new Beam1(player.getX()+18, player.getY(), 0, -15)));
                            break;
                        case 2:
                            t = new Thread(new BeamMoveRunnable(new Beam2(player.getX()+18, player.getY(), 0, -30)));
                            break;
                        default:
                            t = null;
                            break;
                    }
                    t.start();
                    Thread.sleep(200);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class BeamMoveRunnable implements Runnable {
        private Beam beam;

        public BeamMoveRunnable(Beam beam) {
            this.beam = beam;
        }

        public void run() {
            Beam beam = this.beam;
            beams.add(beam);
            try {
                while (true) {
                    if (beam.getY() <= 0) {
                        beams.remove(beam);
                        break;
                    }
                    beam.move();
                    repaint();
                    Thread.sleep(20);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

[コード全体ではありません。確かに問題を引き起こしていないいくつかの行をカットしました]

そのようなエラーが発生します:

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
    at java.util.ArrayList$Itr.next(ArrayList.java:791)
    at spacecommander.MainPanel.paintComponent(MainPanel.java:53)
    at javax.swing.JComponent.paint(JComponent.java:1054)

等々...

問題はどこにありますか?ConcurrentModificationException の意味はわかっていますが、ここで問題が発生する可能性があるかどうかはわかりません。同期を行う必要があるかもしれません。はいの場合、場所を示してください

4

3 に答える 3

1

Before iterating the beams in paintComponent create a copy of the collection and use the copy to iterate.

于 2013-01-08T15:27:22.187 に答える
1

BeamMoveRunnableたとえば、コレクションを繰り返し処理しているときに、別のスレッドでビームのリストを変更しています。

オブジェクトごとにスレッドを作成するのは、かなり無駄が多く、管理が困難です。

各ビームでメソッドを定期的に呼び出して移動するスレッドを1つ用意することをお勧めします。コレクションへのアクセスを同期する必要がないように、ビームが描画されている間はビームを追加または削除しないことをお勧めします。

于 2013-01-08T15:15:07.213 に答える
0

メソッドで反復すると同時にbeams、スレッドBeamMoveRunnable(このオブジェクトをラップするスレッド)で配列リストを変更しています。これが例外の原因です。RunnablepaintComponent

于 2013-01-08T15:13:12.093 に答える