Collision Detection

I've been asked a couple of times how the collision detection works in the Asteroids game I developed on PlayMyCode.  If you've not tried it yet, then you can find a playable link a few posts below.

I'd originally planned to use nothing but Polygon's and a Point-In-Polygon algorithm for collision detection, but then I realised that PlayMyCode had their own collision detection features that allow pixel-perfect hit detection.

Obviously, pixel-perfect detection wasn't going to work well with Polygon's and it's generally slow.  However, in the interest of keeping things simple I tried out a few tests and was surprised at the performance, which led me on to how the collision detection works in Asteroids now.

Each object in the game (player ship, bullets, asteroids, UFO's etc) is rendered as a polygon.  However, rather than drawing and managing polygons on the main canvas, they're rendered to their own separate image first.  This operation is handled inside a Polygon class.

Having each object as an image not only keeps things at a decent rate but also means we can use the per-pixel detection that PlayMyCode provides.

    // Check for a collision between this polygon and that given
    def isCollide(poly, centered)
        return isCollide(poly.Img(), poly.X(), poly.Y(), centered)

    // Check for a collision between this polygon image and that given
    def isCollide(img, ix, iy, c)
        if (@img.isPixelOverlap(@x, @y, img, ix, iy, c))
            return true
        return false

And well, that's basically all there is to it!  The @img is the local Polygon image to which isPixelOverlap() is called against another image (which is every single other -relevant- Polygon object in the game).

There was one other minor thing I had to do - the asteroids are actually filled polygons, but are filled with a very faint colour so as to not be different from the surrounding black!  Why?  Well, there is a rare event, triggered by a lapse in framerate where the player ship could potentially end up inside an asteroid.  Here, the pixel overlap method would fail as their would be no collisions.  Having the asteroid filled in this way means that the player would die instantly as a collision would be detected.  Crude, but it works!

Note: For simplicity, the bullets are all rendered as polygon images rather than pixels.  We can then extend the Polygon class and utilise its collision detection code.

Yes, this could be improved quite a bit.  Currently, the game checks for collisions between the player and every asteroid, every bullet and every asteroid etc.  This is somewhat costly and a better approach would be to limit the checks to objects that fall within the bounding box of the player for example.

However, as the performance doesn't seem to be an issue and I need to finish other projects I've left this for a rainy day - it's simple enough to do and the bounding box mechanism is already in the Polygon class. :)

Feel free to look through the code (available by clicking the CODE button on the PlayMyCode site).


Popular Posts