Java Game:ArrayList和Iterator vs. Thread

时间:2011-06-28 02:09:39

标签: java multithreading arraylist

Sup人。

我正在为我的Java类编写一个简单的僵尸游戏,我遇到了一个小问题:Zombies是我制作的一个类,我在ArrayList上对它们进行处理,如下所示:

horda.add(new Zumbi( (int)(Math.random()* 750), 0));

参数表示屏幕上的僵尸生成位置。要杀死它们,你必须点击它们,非常简单,用迭代器检查碰撞,在这里:

java.util.Iterator<Zumbi> itr = horda.iterator();
        while (itr.hasNext()){
            Zumbi z = itr.next();
            if (tiroPos.x > z.zumbiPos.x && 
                tiroPos.x < z.sprite.getWidth() + z.zumbiPos.x &&
                tiroPos.y > z.zumbiPos.y &&
                tiroPos.y < z.sprite.getHeight() + z.zumbiPos.y){

                //things to do when it hits    
            }

tiroPos是一个指针,用于保存玩家射击的坐标。事情是:有时当你击中僵尸时应该发生的事情没有发生。我不知道是不是因为Iterator运行速度不够快或其他事情。

也许为每个僵尸制作一个不同的线程,但这会改变代码是一些基本方法,如果它没有帮助我不想冒失去所有时间。

那么,有什么想法吗?

//编辑:忘了说:我正在检查Overrided paint方法中的碰撞,因为我不知道如何在其他方法上绘制东西,当我尝试访问ArrayList时(它是另一个线程上的Sync'd ArrayList)它给我一个共同修改的异常。

// EDIT2: 问题解决了(从未有过)。

MouseEvent传递的MouseListener对象传递鼠标指针下端的坐标。所以它不是真正的碰撞问题,而是更多的数学问题。我必须比较clickPoint.y - 25 以使其正确。

感谢所有试图提供帮助的人!

4 个答案:

答案 0 :(得分:2)

要记住两件事:

  1. 如果需要在迭代过程中从ArrayList中删除项目,则必须通过迭代器上的remove()方法执行此操作。如果您修改列表本身,它将失败。

  2. 如果两个线程正在访问列表,则应使用Collections.synchronizedList包装它,或选择其他数据结构。

  3. 编辑:听起来你正在修改一个线程上的列表,而在另一个线程上迭代它。这将导致ConcurrentModificationException。避免它的最简单方法是在两个线程上使用synchronized块包装列表的用法。例如:

    synchronized(horda) {
        iterator = horda.iterator();
        while (iterator.hasNext()) {
            z = iterator.next();
            ...
        }
    }
    

    另一种方法是在迭代之前克隆列表,或者使用java.util.concurrent中的一个特殊列表实现,例如CopyOnWriteArrayList

答案 1 :(得分:0)

多线程只能对你有所帮助,而且它实际上取决于你拥有多少处理能力。

四叉树通常用于碰撞检测,因此可能值得研究,作为替代方案。

答案 2 :(得分:0)

在我看来,你最好使用for-each循环迭代僵尸。它是为执行这样的任务而引入的,所以你也可以使用它。

答案 3 :(得分:0)

我假设玩家通过点击窗口“射击”,因此tiroPos是点击的x,y坐标。

如果是这种情况,并且你的问题是,当用户点击很多时,某些僵尸似乎没有被点击,那么可能只有最后一个“镜头”被保存在{ {1}}。

您可以通过在for循环周围添加适当的tiroPos调用以及设置System.out.println()的另一个调用来测试此问题。如果在for循环中间tiroPos发生了变化,那就是为什么有些僵尸没有被射击。

如果是这种情况,您需要开始存储点击列表,而不仅仅是最新点击。

编辑:但这不会修复您的并发修改例外。