views:

219

answers:

6

Hi all ... 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://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar

+1  A: 

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--);
        }
    }
}
Roman
@Roman when using your solution it deletes if there is intersection but if player fires repedetaly lots of fire it creshes..
Meko
+1  A: 

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.

Carl Smotricz
@Carl your solution gives IndexOutOfBoundsException also.
Meko
Now that you mention it, I can understand how. Oops! I'll update my answer to reflect this.
Carl Smotricz
+6  A: 

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.

Frank
+1 I couldn't catch why the exception occurs before reading your answer. Now I see at least 1 case: when he compares last computer bullet with other bullets, then removes last computer bullet, and then continue to compare, the exception is thrown.
Roman
+7  A: 

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
lorenzog
+1. This is the solution. It handles not only 1 computer bullet vs 1 user bullet collision but also 1 computer bullet vs N user bullets in the same place collision
Roman
A: 

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);
    }
neverend
where is the wrong
neverend
Hi... I used your idea for cb.size() -1 ad it worked in my original code...But maybe it gives any error but I payed it 10 times and it doesnt give error )))
Meko
@Meko not getting an error is not a valid proof that it is (logically) correct. If you want to compare each user bullet with each computer bullet, you need a 2-pass algorithm as described by @lorenzog (If you have o *triple-collision*, two bullets will be deleted, the third not)
Carlos Heuberger
@neverend HI like @Carlos sad it doesnt delete some bullets //I didint recognise ,my game was fast and lots of bullets.I changed it to one shot and some bullets not deleting.But in game you cant recognize :)
Meko
+1  A: 

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;
Zarkonnen