开发者

Java IndexOutOfBoundsException

开发者 https://www.devze.com 2022-12-23 08:50 出处:网络
I made an little shoot em up game..It works normal but I want also implement if firesintersects they will disappear. I have two list for Player bullets and for computer bullets ...But if I have more b

I made an little shoot em up game..It works normal but I want also implement if fires intersects they will disappear. I have two list for Player bullets and for computer bullets ...But if I have more bullets from computer or reverse .Here my loop

     for (int i = 0; i < cb.size(); i++) {
        for (int j = 0; j < b.size(); j++) {
            if (b.get(j).rect.intersects(cb.get(i).rect)) {

                cb.remove(i);
                b.remove(j);


                continue;

            }
            if (cb.get(i).rect.intersects(b.get(j).rect)) {


                b.remove(j);
                cb.remove(i);

                continue;

            }

        }

    }

This is my game which woking algoritms... http://rapi开发者_如何学Cdshare.com/files/364597095/ShooterGame.2.6.0.jar


I highly recommend against playing with the for loop counters from within the loop itself. You are careful now, you won't be careful later ("let's try a hack here to debug") and end up with bugs.

One solution could be:

  • check whether two objects intersect
  • if they do, save a reference into a separate list of thingsToRemove
  • finally, go through the thingsToRemove and remove (or set to 'null', or -1 or whatever) the corresponding elements in the cb and b lists


As stated in Carl's comment the second if should be redundant.

As for your IndexOutOfBounds exception, this is caused by the following: When a computer bullet hits a player bullet, you remove both from the lists. Using continue you then continue comparing the same computer bullet to the remaining player bullets. However, that computer bullet was already removed before! Hence, I suggest you break instead of continue, then the next computer bullet is checked for intersection with player bullets.

As Roman hints at with his code you should further decrease the outer loop's counter, as you reduced the list size by removing one of the bullets. Hence, what used to be bullet #3 is in the next iteration what previously was bullet #4. So after the break you don't want the increment of the outer loop's counter.


the simplest modification to avoid logical error:

for (int i = 0; i < cb.size(); i++) {
    for (int j = 0; j < b.size(); j++) {
        if (b.get(j).rect.intersects(cb.get(i).rect)) {
            cb.remove(i--);
            b.remove(j--);
        }
    }
}


The problem with your code is that you are changing the size of list cb whenever you find an intersection, but then continue using the same index. For example, if cb has 3 elements and b has 4, and the 3rd (index = 2) computer bullet intersects the first player bullet, the size of cb is reduced to 2. When you then go on to check the second player bullet against the third computer bullet, there are only two items left in cb, and the game crashes.

In short, looping over lists and modifying them at the same time is difficult.

The other thing to consider is that if, for example, a computer bullet intersects with two player bullets, all three of them should be deleted. But if the computer bullet is deleted when it encounters the first player bullet, the second player bullet will remain.

In fact, there could be chains of bullets all touching one another, so deleting anything from the list before you've done all the intersections can lead to wrong results.

After a hilariously long time spent thinking about this, here's what I'd do. It ensures that everything that needs removing is removed and doesn't rely on index-munging.

ArrayList<Bullet> newB = new ArrayList<Bullet>(b);
ArrayList<Bullet> newCB = new ArrayList<Bullet>(cb);
for (Bullet pBullet : b) {
    for (Bullet cBullet : cb) {
        if (pBullet.rect.intersects(cBullet.rect)) {
            newB.remove(pBullet);
            newCB.remove(cBullet);
        }
    }
}
cb = newCB;
b = newB;


Running the loops backward should also do the trick:

for (int i = cb.size() - 1; i >= 0; i--) {
       for (int j = b.size() - 1; j >= 0; j--) {

EDIT: This solution can also encounter OOBE's. There are some unhandled cases... so I must recommend one of the higher-ranked solutions rather than this.


n my opinin, you can write in this way

   for (int i = cb.size() -1; i >= 0 ; i--) {
            boolean bremoved = false;
        for (int j = b.size() -1 ; j >=0 ; j--) {
            if (b.get(j).rect.intersects(cb.get(i).rect) ||
                cb.get(i).rect.intersects(b.get(j).rect)) {
                  bremoved = true;
                b.remove(j);
            }
        }
        if(bremoved)
            cb.remove(i);
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号