This tutorial will look at different ways to get meaningful information about the collisions in Box2D.
local contactEdge = body:GetContactList() while contactEdge do local contact = contactEdge.contact contactEdge = contactEdge.next endor you can iterate all contacts:
local contact = world:GetContactList() while contact do contact = contact:GetNext() endAdditionally a reference to the "Contact" object is provided when using ContactListeners.
function b2.Body:IsTouching(other) -- iterate contacts local contactEdge = self:GetContactList() while contactEdge do -- look for a specific body if contactEdge.other == other then -- make sure there's actual contact if contactEdge.contact:IsTouching() then return true end end contactEdge = contactEdge.next end return false endNote that the code above returns true even if there is no "solid" contact. Non-solid contact occurs when one or both of the contacting fixtures is a "sensor". Therefore, the approach shown above is pretty good if you want to add "sensor triggers" in your game.
Keeping in mind that all fixtures in Box2D are convex,
it's easy to realize that there cannot be more than 2 contact points
between the same pair of fixtures.
However, one fixture may be in contact with two or more other fixtures. Therefore a body can have several contacts acting upon it at the same time:
Four contacts with the contact points shown in white
Left: circle with 2 contacts (1 point each)
Right: rectangle with 2 contacts (1 point each)
Using "contact:GetWorldManifold()" and "contact:GetManifold()" functions we can easily determine where a contact point is located in world or local coordinates.
worldManifold = b2.WorldManifold() contact:GetWorldManifold(worldManifold) contactPoint1 = worldManifold.points contactPoint2 = worldManifold.pointsAnother useful part of the "worldManifold" is the "collision normal" (see yellow lines in the figures above). Each contact has a "collision normal" which is basically the "axis of shortest separation". In layman terms, it's a (normalized) vector describing the direction in which the two fixtures are "pushing" each other.
-- collision normal normalVector = worldManifold.normal
force = mass*acceleration acceleration = changeInVelocity/time changeInVelocity = finalVelocity - initialVelocityAn impulse is similar, but with "time" removed from the equation:
impulse = mass*changeInVelocity changeInVelocity = finalVelocity - initialVelocitySo you can think of an "impulse" as an instant change in velocity of an object times its mass.
Each contact point has an impulse associated with it. Box2D describes the magnitude of these impulses in two parts:
manifold = contact:GetManifold() -- impulse for the first contact point manifoldPoint1 = manifold.points -- normal impulse -- separates or pushes the two fixtures apart and is always positive normal = manifoldPoint1.normalImpulse assert(normal >= 0) -- tangent impulse -- simulates friction between the two fixtures and could be negative tangent = manifoldPoint1.tangentImpulseThe direction of these impulses is determined by the "collision normal".
impulse = changeInVelocity*mass changeInVelocity = impulse/massKeep in mind that the exact point where an impulse is being applied is important too. The location of the contact point along with the center of mass of each body may produce torque and cause the body to spin.
listener = b2.ContactListener() function listener:PostSolve(contact, impulse) -- here we now we know what impulses are being applied end world:SetContactListener(listener)One downside is that the "PostSolve" callback may be evoked many times during a single update step. I don't recommend "PostSolve" unless you need to know every impulse that is applied between fixtures.
Box2D API by Erin Catto