Uniqueness of Post-Collisions

Almost every developer who uses Corona's Box2D-based physics engine implements some type of basic collision detection after all, a physics simulation without any collision events and associated game logic would be fairly lifeless.

For those developers who need even more specialized collision handling, Corona also features the pre-collision listener. This is reserved for specific, dedicated handling of a collision before it occurs and it's often used with the PhysicsContact as discussed in the Multi-Element Collisions tutorial.

Yet a third option — less known but equally important in some cases — is the post-collision listener. As the name indicates, this listener is used to gather various details of a collision after it occurs. This event also provides some physical information that no other event type provides, making it especially useful in certain cases!

Configuring Post-Collisions

This tutorial won't go into extensive detail on how to set up collision listeners since it's all outlined in the Collision Detection guide. Basically, post-collisions are configured similarly to normal collisions:

-- Set up physics engine
local physics = require( "physics" )
physics.start()

-- Create a basic physics object
local box = display.newRect( 60, 20, 50, 50 )
physics.addBody( box )

-- Set up the post-collision listener function
local function postCollisionEvent( self, event )
    print( "POST-COLLISION EVENT" )
end

-- Associate the listener function with the object
box.postCollision = postCollisionEvent
box:addEventListener( "postCollision" )

Be aware that post-collision events are quite "noisy" and may report many times per collision contact. This may affect game performance, so you should only listen for post-collision events when necessary. For instance, you may consider temporarily removing the associated event listener when post-collisions are not a factor within the simulation:

box:removeEventListener( "postCollision" )
box.postCollision = nil

Post-Collision Applications

It may seem pointless to gather details about a collision "after the fact" since the collision has already occurred and the physics engine has essentially moved to the next time step. However, it's exactly the instances where post-collisions are important that makes them an essential part of your physics toolbox.

Let's explore some potential instances where post-collisions are unique and powerful:

Detecting Collision Force

The post-collision event is the only collision event which reports the force of the collision which just occurred. This value is reported as event.force in the post-collision listener, for example:

local function postCollisionEvent( self, event )
    print( "POST-COLLISION EVENT" )
    print( "FORCE:", event.force )
end

Where might this apply in a physics simulation? Consider the classic hit Angry Birds where each ornery avian has a different effect on different solid materials in the world — for example, the small blue birds strike particulary hard against "glass" blocks. If we were to implement similar game functionality, it would be easy to code a conditional check which detects if a blue bird collides with a glass block, but that limits us to a true/false relationship — we still wouldn't know exactly what force was delivered in the collision. Using the post-collision event, however, we can detect the amount of force and assign damage accordingly, either shattering the glass block entirely or merely cracking it partially.

Threshold Filtering

Collision forces are equally useful in "filtering" purposes. Consider a game where the player fires arrows at an armored enemy, for instance the armored skeleton in the Multi-Element Collisions tutorial. In theory, the skeleton's armor has a certain threshold upon which it will block projectiles entirely, causing them to bounce off and fall to the ground. As noted above, a normal collision event can reveal that a projectile hit the skeleton, but it cannot provide details about collision force. Thus, the post-collision event once again becomes crucial — by implementing it, we can detect if the force is above a certain threshold and, if so, the arrow will penetrate the enemy's armor and deliver an appropriate amount of damage.

Detecting Collision Friction

The post-collision event is also the only collision event which reports the friction of the collision which just occurred. This value is reported as event.friction in the post-collision listener, for instance:

local function postCollisionEvent( self, event )
    print( "POST-COLLISION EVENT" )
    print( "FRICTION:", event.friction )
end

Where might this apply in a physics simulation? One example would be to detect the friction of a car or other object when it collides with a metal surface, then use that value to display a variable amount of "sparks" via a particle emitter or other means. For example, if the friction is very high, we could generate a more visible amount of sparks, while if the friction is low — for instance the object just barely brushed against the surface — we could generate just a small burst of sparks (or even use the filtering threshold discussed above to omit the effect entirely).

Conclusion

Hopefully this tutorial has outlined some valid applications for post-collision events. While detecting these will never be as common as detecting normal collisions, they are unique events which can be essential to certain game logic and even to visual realism in a game.