Thursday 14 June 2012

Power Up - Discoveries in Collision

When I started Power Up, one of the scariest aspects of it was collision detection. I was only too aware that as a fairly fast paced shooter, any problems with collision would particularly damage the game.

As mentioned in earlier posts, everything I had made proviously, I had made in Director and was exported as Shockwave files or little Windows .exes. With collision, Director allowed me to essentially just use a mask of the image in question as collision. Basically, when two sets of pixels intersected they would act accordingly. (I click the box... Director does the rest. Nice). It took me a few games to figure this out though so at first I was limited to basic box collision. Having experienced that first hand, I really know how non-ideal it is.

Basic Box-Collision Nightmares!! These sprites from my first self-made game, "Diz" (circa: 1998-99) were a lesson in character design for bad box collision!


Box collision is basically just that. A big bounding box which surrounds the image and dictates whether or not it collided with something. Sounds fairly simple and effective eh. Well it is certianly simple... and that's really the problem.
From my point of view, with simple bounding box collision you've got your pros and cons. Pro: It's simple, dealing with 4 points and the straight lines between them. This, I'm told (by real programmers), makes it easier on the processor. Cons: if the sprite is not a perfect square/rectangle, there's bound to be some empty space in the image that acts like it collided. (usually the corners).

This is a biggie! While I could accept my early games looking ropey in the collision department, I needed to find an alternative.

---

Recently, a much better suggestion was made. "Bitmap masking". This is basically the same as what Director offered all those years ago. Trouble is, XNA has no "masking on" button for your sprites and I must have missed the tutorial. Now I have half a game with far too many baddies comitted to it for me to just bulldose through them all completely changing the collision type... I've got to learn it first too. All of that would heavily effect my estimated release of "Early-2013" which I've already pushed back, cramming all that needs to be done between now and then.

Nope. The sensible thing to do first was to look at the code I was already using, to become much more familiar with it and to figure out if/where it was perhaps a little more versatile than I first assumed it would be.
Without boring you with code snippets, I found it was actually quite versatile. By applying a little of what I'd recently learned about c#/xna syntax, I was able to make a few generalised adjustments to the collision rectangles.

Originally, the collision rectangles were set to the width and height of the sprite in question, placing their hot-spot at 0,0 (their top left) or at the centre of the sprite. (depending on what messes I'd previously left while learning).

What we currently had was box-collision around the edges of all the sprites. The usual corner-collision problems would ensue unless I thought of something...


Basic Box-Collision (mock-up): See how the boxes surround the whole image, and in some cases, the whole animation? Just look at all that horrible, collideable empty space.


Basically, by consistently placing the centre of the rectangle at the centre of the sprite (width/2, height/2), I could then reduce the rectangle somewhat. Whether this was to pull say, 10 pixels off the height and 20 pixels off the width, or to apply something like (width/3*2, height/3*2) to get a rectangle that was two thirds the width and height of the ship, I was able to adjust and play around with the size of the rectangle until it played right!

So now I could manipulate the size of the collision rectangles for pretty much everything in the game. How could I use that to make cheap collision feel well, a little less cheap?

---

Basically, the last thing I wanted was a bad review because the player suffered a cheap death through a collision with a transparent corner of a baddie's rectangle. Regardless of how many baddies and bullets I throw at the player... regardless of how many hits said baddies require to kill and how fast and accurate said bullets fly... regardless of all the balance issues that will hopefully start out fairly easy with practice, becomming more difficult until things are suitably challenging for those hellish final levels... despite all that, the collision must be FAIR. If I can't get it to be fair because of its rectangular limitations then it must always go IN THE PLAYER'S FAVOUR!

Now, I know a few people are expecting something particularly ground breaking here, but it's not. Bearing in mind that this is my first go at xna and having done some basic Shockwave game coding previously, I'm basically just applying a little latteral thought to the processes, this is how I'm doing it.

*As the player, your collision remains INSIDE your ship.
*The collision for your enemies remains INSIDE their ships.
*The collision fir their bullets goes INSIDE them (though these are pretty small and probably don't need as much attention, so scratch that).
*The collision for your bullets stays OUTSIDE like a bounding box. (Making nice big collision areas. If in doubt, make it connect with that baddie!)
*And as for pickups, OUTSIDE. We want those nice beneficial things to be as pick-uppable as possible.

there, looks fair to me.


Modified Box-Collision (Mock-Up): with a simple general 2/3rds reduction, collision detection becomes much tighter and at little to no extra cost. Notice that boxes for player projectiles, pickups and small enemy bullets remain their original size.


So, here we have a situation in which the player should very rarely, if ever, actually collide with an enemy's empty corner and die. If anything, the player will always be given a couple of pixels' grace with which to fend off a few close calls. Because of the adjustments to the player collision and the small size of the enemy bullets, the same applies with those. Should the player ever die, it should only be from a definite case of head on collision or a clear contact with a projectile. In theory (and so far, in practice), collision with an enemy or bullet should never be in dispute.

However, applying wide collision to your own bullets gives you a generous advantage. If collision is ever in contention, it will only be slight and always to the player's advantage.

All that with the simplest, cheapest kind of collision type available.

Now, I might find that the Xbox 360 (or whatever we're playing on by the time this gets out) can handle the ammount of sprites I'm churning out alongside all the projectiles, explosions, audio and of course, accounting for my not particularly well optimised first go at game coding. If that is the case, I'll pour a lot more time into much more technically impressive collision types in my next games.

As far as Power Up is concerned, this is all work-in-progress. Some of it is implemented, some of it is a bit rough around the edges. Later, I'm planning to put some extra time into getting this collision type as close to spot on as I can, but that's all for nearer to submission. At the moment, the main thing is that the concept works. Unless it stops working I'll see it through throughout the project.

Again, thanks for taking the time to read my blog. See you in the next one...

16 comments:

  1. I don't know if the libraries you're using can do what I'm about to suggest, but at least it can be something to help you come to a new solution that might be better.

    Instead of box collision (too simple) or pixel-perfect collision (too much processing) you could try poly collision. The idea is that you use a polygonal shape over your game sprite, instead of a box. You can cut away those corners and make a shape that is still simple (6 sides ain't so bad) but better reflects the shape of your sprite.

    ReplyDelete
    Replies
    1. Hiya. Thanks for the comment. Good to know it's being read. ;) This sounds like another really good suggestion and something I'll look into.

      Other good ideas have included multiple boxes for more complex enemy shapes, detecting pixel collision only after the boxes have collided and splitting the screen into quadrands to quantise the game's attention on what collides with what.

      Polygonal work is something I've never tried so might take some intensive study, but the same applies to all the other ideas really too. I reckon I'll probably tune this simple method I'm currently using as best as I can for this game, then look into a few more interesting ones for my next game.

      Delete
    2. Another method is to use bitmap masks. You load up or calculate the masks while loading and creating ur sprites and then use those masks to check overlapping areas. Check out this link: http://www.gamedev.net/page/resources/_/technical/game-programming/collision-detection-r735.

      Delete
    3. Thanks! I'm building up quite a library of cool stuff to experiment with. This is definitely one. I love that it doesn't even look at the pixels until the bounding boxes have been tested. Seems so obviousnow but I hadn't even considered that!!

      Delete
    4. Mind you I'm just starting with XNA as well, but can't you use more than one type of collision detection? Like use the less intensive box type collision detection for power ups and better, more intensive detection for ships?
      What you did seems pretty fair, though. I wouldn't complain to much if that's what is used in the final game. I definitively know the one about not wanting to rewrite code. Spending hours on something just to dump it all sucks. But then again, I would go great lengths to make the program play better. Trying to be (close to) perfect is crazy!

      Delete
    5. Agreed. It's really just a balance between making it work and getting it done in a reasonable timeline. I reckon I'll take this path with the collision on this game then toward the rnd I'll go back through everything in it and make sure it's all as tight as it can be.

      Delete
    6. It's been quite some time since I originally left this comment, but in that time I've rummaged through XNA and put together a decent polygonal collision detection system. The reason why I mention it here is that I found it to be easier than I originally thought it would be.

      I found that doing it had two huge benefits over bounding box collision detected. The first is that I could just create a subclass to my polygon class that had constraints to make it a rectangle only, so I could effectively do bounding box collision anyway. The other benefit was that now I could rotate my "bounding box" collision. To illustrate that benefit, check out the three missiles fired from the player ship in the last screenshot of the post. When they rotate so as not to be horizontal, the bounding box gets a lot bigger than it should. With the polygonal rectangle, it just rotated with the object.

      If you want, I can send you the code to look at. It should be very easy to implement into just about any 2D game.

      Delete
    7. Hi Timothy. I'd love a nosey at that! If I don't get the time to properly implement it into Power Up I'll definitely give it a go with my next effort. Any chance you could send a bit to my email address? It's psychoticpsoftware@gmail.com
      Cheers man!

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Interesting read.
    Simple collision will usually suffice for simple flash games, however, for products you want to put on the market collision has to be tightened up to some degree. The way you've proposed of tackling the problem would probably work for the shoot-em-up style game you're making, but i don't think it would work for more complex games.

    Good examples of bad collision include shooting through the windows on the Ford Nucleon style cars in Fallout 3 and I think some clutter objects in Modern Warfare 2's "Trailer Park" map.

    (The first time I tried to fire at Arkansas the minefield sniper through that car window in Fallout 3, I got really ticked off when the bullet hit the car's collision box and blew the car up.)

    ReplyDelete
    Replies
    1. Yeah. I'll bet that was annoying. I find that in current gen 3D games collision has to be spot on. I know people who use Unity to make games and they're pretty much using the actual environments as their own collision. Sounds pricey but I know they're a lot cleverer than me. I'm sure they've figured out some really smart ways of quantizing it all. Lol, maybe one day I'll get to that point but for now I'm happy with my little spaceships and boxes.

      Thanks for reading and commenting on this. ...Makes it all worthwhile. :D

      Delete
  4. Hello! First of all thanks for the twitter follow. Looks like we have very similar blogs going.

    You mentioned Unity; well I'm developing for Android with Unity and I can tell you that doing per-polygon collision is usually not the way to go. Far too CPU expensive on mobile. But similar to the problem you're having, box colliders just aren't good enough in many cases.

    The solutions are remarkably similar to the ones you've gotten here for 2D. One is use a bunch of box colliders to make a blocky form that is roughly the right shape. The other is to make a second, very low poly version of the mesh, turn of its renderer and make it a child of the high poly object. You then use the low object for collision detection; if you've done a good job of creating an object that is much simpler, but the right shape, you're good to go.

    ReplyDelete
    Replies
    1. Glad to hear that collision with 2D and 3D games is so similar. I'm sure that knowledge will come on rather useful later on. Interesting that you can just make really low poly versions for 3D collision. Makes perfect sense really.

      I'm actually quite looking forward to getting into playing with Unity. My coding needs work first though, Think I'd better learn to walk before I can run and do a couple of more c# intensive projects first. That way, Hopefully I'll be able to make something a little more cool and unique once I hit anything like Unity than I would if I were just playing with what's already there.

      Thanks for reading the post and for commenting. :)

      Delete
  5. Hey, thanks for the twitter follow, always nice to meet other game dev.

    I spent my senior year in college working on a 3d space sim game in xna. Collision is a huge pain in xna at time. Sounds like you have a good solution going here for your game.

    bounding boxes have always served me well when working in 2d. unless you end up with more complex sprites. Then you might have to use multiple bounding boxes or go with a different collision method.

    ReplyDelete
    Replies
    1. Yeah. I'm thinking about doing just that for certain baddies. Think I'll do another few collision passes before I'm done with this game eh. ;)

      Thanks for the comment. Would love to see your 3D space game. Was thinking about doing one someday myself. Wouldn't know where to begin at this point though, so we'll see.

      Delete
    2. Well I am no longer working on it, I do hope to one day get to finish it. You can still play the current version. Its not the easiest of projects but it is fun.
      http://evac-game.com/

      Delete