简体   繁体   中英

Collision Detection - Any Language

I'm writing a simple game right now and I need to be able to detect collisions between many objects (checking if 10 objects collide with any 20 other objects but not between the two groups). I've written some simple code that works now but causes the game to slow down extremely after I detect the collision (in Java by the way):

        //Check for collisions between tanks and bullets
        ArrayList<Object> objectsToRemove = new ArrayList<Object>();
        for (int i = 0; i < tanksOnScreen.size(); i += 1) {
            //Get tank
            Tank tank = tanksOnScreen.get(i);

            for (int e = 0; e < bulletsOnScreen.size(); e += 1) {
                //Get bullet
                Bullet bullet = bulletsOnScreen.get(e);

                //Check for collision
                if (tank.collides(bullet.x, bullet.y, 10, 10)) {
                    System.out.println("Collide");
                    objectsToRemove.add(bullet);
                    objectsToRemove.add(tank);
                    break;
                }
            }
        }

        for (Object obj:objectsToRemove) {
            if (obj.getClass().equals(Bullet.class)) {
                bulletsOnScreen.remove(bulletsOnScreen.indexOf(obj));
            } else if (obj.getClass().equals(Tank.class)) {
                tanksOnScreen.remove(tanksOnScreen.indexOf(obj));
            }
        }

And the collides() method of the tank:

public boolean collides(float px, float py, float pwidth, float pheight) {
    // If the distance between the two centers of the lines on x and y axis
    // Is less than the distance of half the w and h added together, the objects
    // Are colliding
    float x1 = (px > x) ? x : px, x2 = (px > x) ? px : x, y1 = (py > y) ? y : py, y2 = (py > y) ? py : y;
    float w1 = (x1 < x2) ? width : pwidth, w2 = (x1 < x2) ? pwidth : width, h1 = (y1 < y2) ? height : pheight, h2 = (y1 < y2) ? pheight : height;
    if ((x2 + w2/2) - (x1 + w1/2) < (w1/2 + w2/2)&&(y2 + h2/2) - (y1 + h1/2) < (h1/2 + h2/2)) {
        return true;
    } else {
        return false;
    }
}

I assume the lag is because of the double for loops, to iterate over the objects. I'm not sure how to eradicate these for loops or how to get the bullets in a certain region of the screen and only check these bullet without using another for loop (segregation, I think). Can anyone point me in the right direction for collision detection with many objects? I don't mind what language the answer is in, even if it is pseudo code.

Thanks,

Ben

Edit 1

I'm right now using the Slick graphics API for java, which provides you with an update and render method to add rendering and game logic. I placed this collision detection in the update method (which is getting called every frame - about 60 times a second). The slowness occurs after the collision happens, and the objects are removed from the screen - which I find odd. Maybe a break command after deleting the objects in the for loop will eradicate it?

Edit 2

Thanks for all the answers guys, and the references are a great help for the future. I fixed the problem only by swapping the bullet and tank for loops, so it didn't continue to loop after the bullet was destroyed. I shouldn't have asked the question, as it was quite easy to fix in the end. Dave and Banthar were right in saying that the problem wasn't with the code, and that it should be instantaneous.

One good idea is to use octree . As the bullets will be moving I assume that you will need a kinetic version of it - there are a bunch of articles on kinetic data structures on the internet.

Also if you want to detect collisions between more complex convex polygons, I recommend you to use gjk algorithm which is very fast for such calculation. Note that this will speed up only the collision detection time for a pair of objects, the number of pairs will still remain the same.

Unless I'm missing something, or there's additional code you haven't shown, you're running in O(n^2), where n is 20. It should seem instantaneous to the user.

Try stepping through it in the debugger to see where it's slowing down.

Edit to elaborate: your expensive operation is not in the code you've posted. It's somewhere else, being called by the code you've posted.

Thanks for all the answers guys, and the references are a great help for the future. I fixed the problem only by swapping the bullet and tank for loops, so it didn't continue to loop after the bullet was destroyed. I shouldn't have asked the question, as it was quite easy to fix in the end. Dave and Banthar were right in saying that the problem wasn't with the code, and that it should be instantaneous.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM