2
\$\begingroup\$

I am writing a "Gauntlet" style game. So far I have managed to successfully detect collisions between my player object and my ghost enemy objects, and when they collide they drain the player's energy.

The Ghosts are stored in an ArrayList. I now have bullets which the player can fire, these are instantiated from the Player class and added to another ArrayList called bullets.

I typically have around 50 ghosts on the screen dotted around the map.

ArrayList<Ghost> ghosts = new ArrayList<Ghost>();
ArrayList<Bullet> bullets = new ArrayList<Bullet>();

The ghosts and bullets are added to these lists when spawned/fired

I have tried to implement a method as per below, to try and determine whether a ghost's bounding rect and a bullet's bounding rect overlap, as follows:

/**
 * Check if a ghost has been hit by a bullet
 */
public void checkGhostsHit() {

    Iterator<Ghost> iterEn = ghosts.iterator();

    while ( iterEn.hasNext() ){
        Ghost g = iterEn.next();

        //initialise the bullet iterator each time here
        Iterator<Bullet> iterBul = Player.bullets.iterator();

        while ( iterBul.hasNext() ) {
            Bullet b = iterBul.next();

            if ( b.getBoundingRect().overlaps( g.getBoundingRect() ) ) {
                Gdx.app.log("Enemy", " Hit");
                iterBul.remove();
                iterEn.remove();
            } 
        }
    }
}

This method is being called from my main render loop but I cannot get it working for love or money. I have tried various forms of the above method, including 'For' loops etc.

Am I performing the check in the correct place? Should the Bullet class instance iteself be checking for a collision, or is the above approach the correct idea.

As you can tell I'm a noob to this and I am still struggling with working out which activities should be undertaken by particular game Classes.

\$\endgroup\$
4
  • \$\begingroup\$ UPDATE: When I reduce the number of ghosts in the game to say five, the detection starts working, so I guess it must mean that the Iterator cannot get through the list quick enough. So the question now is "how to I only iterate the ghosts which are in view?" \$\endgroup\$ Commented Jul 8, 2015 at 8:30
  • \$\begingroup\$ Whatever your problem is, I don't think it's in the code you posted. Looks correct to me. \$\endgroup\$
    – tandersen
    Commented Nov 6, 2015 at 19:00
  • \$\begingroup\$ Hi James, I've removed your "update"/follow-up question since it should be asked in a new question. (Granted, that may be 2 years ago, so if this isn't relevant to you any longer, don't worry about it.) \$\endgroup\$ Commented Jun 6, 2017 at 12:34
  • \$\begingroup\$ Your code looks like it will throw a ConcurrentModificationException when the bullets finally start hitting. Avoid using iterators if you're going to add or remove from the list while iterating. \$\endgroup\$
    – Shaun Wild
    Commented Jun 6, 2017 at 13:18

1 Answer 1

2
\$\begingroup\$

I guess the problem here is the so-called Tunneling.

Tunneling happens when an object moves to far in one update loop and therefore the collision is never detected, as it "jumps over" the other object.

There are several ways to solve this:

  • Continuous Collision Detection: Instead of checking for an overlap at the current posiition, you could use the way from the last to the current position as the bounding box. Doing this, you would detect the collision, even if you would not collide at the new position.
  • Fixed update time: Instead of using delta as update time you could use a fixed time (lets say 1/60second) and use an accumulator-approch (look at the code here). This makes sure, that the updates have a fixed time, so the way an object can travel in one update-loop is limited. Also the calculation of the logic usually takes less time then the rendering, so you can perform it multiple times/render loop without problems.
\$\endgroup\$

You must log in to answer this question.

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