Area Weapons and Explosions in Box2D
I’m going to deviate slightly from just posting about progress on Leges Motus to talk in slightly more technical detail for a bit. Recently, for the game, I decided to implement area-of-effect weapons (explosion-like or otherwise blast-like kinds of guns).
The main goal here was not to create a realistic-looking explosion with particles and exact, perfect rotational energy on the items hit – there are some other good discussions of the issues involved in things like cover, rotational motion, and so forth here, here, and here.
Instead, I want to talk about simply determining which bodies are hit by the explosion/area of effect, when it is non-circular. For things like cone-shaped blasts, you can’t just use the AABB to find the objects affected.
I decided to create a new body, with a sensor (not a fully physical fixture) using the position and shape (as a b2Shape) defined for the blast. This has the advantage that it can detect hits of any shape and size, but it has the disadvantage that it requires waiting until after the next physics tick to determine what has been hit. Fortunately, if you set the shape up before the tick and apply the results immediately afterward, it takes only one frame extra, so it’s not a big problem. The other complication because of this, however, is that you must keep track of all the information about the shot until you get the results. For this, I used a “Bullet” class, storing an ID, position, and the weapon ID of the fired weapon, as well as which player fired it.
This works best if you have a PhysicsObject wrapper class that is passed in as userdata on your Box2D bodies, so that you can always determine what type of body is hit and cast to it, then call the appropriate methods to resolve the hit.
Now, you’ve got a list of players or other objects that are within the area, but you’re not done yet. Whenever you receive information about a hit, you have to make sure that the object isn’t blocked by others. To do this, I used a simple raycast at each vertex of the object (not just the center, because the center could be blocked without all the edges being safe from the blast). If any of the rays hit, the object is affected. Note: Though I don’t bother with it, as it isn’t terribly essential for Leges Motus, you can take this further and actually determine the percentage of the object that is affected and apply force/damage appropriately, but it’s a bit tricky.
So now, we’ve got a method to find all objects affected by an explosion or area of effect, using nothing more than the built-in Box2D functionality. Pretty cool, eh?
If you want to see the actual code, it’s available in the open-source Leges Motus project. You can either check out the SVN repository or view the specific files (common/AreaGun, common/Bullet, and newclient/GameLogic) using the online SVN viewer.