How can I get the force of a collision in Love2D?

Is it possible to get the force of a collision between two objects in Love2D/Box2D? If so, how?

• rigidbody.velocity.magnitude is a velocity, not a force. And you can't get the force of a collision from the velocity of one object, you need information about the other object as well. Do you want to know how to get the velocity, or the force? And when do you want to get it? – MichaelHouse Jan 1 '14 at 16:51
• @Byte56 ok, thanks, I want to to get the force of the collision. – CharlesL Jan 1 '14 at 17:43

You have access to the b2ContactImpulse in the PostSolve callback on the b2ContactListener. The normalImpulses field on b2ContactImpulse holds an impulse applied to both bodies in the direction of the contact normal.

An impulse is calculated as a change in velocity times the mass of the object, so the normalImpulses well describes how hard the two fixtures hit each other. Given the same relative velocity between two fixtures, the greater the sum of the masses of the fixtures, the greater the normalImpulses.

An impulse is equal to a force acting on an object over a period of time, so if you need to calculate the actual force, you can divide the impulse by the frame time you passed to the Step function and you should get a reasonable assessment of the actual force acting on the two objects, though since i don't understand the inner workings of Box2D, i don't know how accurate this assessment is. If you're just interested in gauging the force of impact, not in the strict physics sense, then using an impulse is just as effective.

World:setCallbacks( beginContact, endContact, preSolve, postSolve ) may solve your problem.

The postSolve function receive two fixtures and a Contact object (https://love2d.org/wiki/Contact).

A very good article: https://love2d.org/wiki/Tutorial:PhysicsCollisionCallbacks

You can use normalimpulse in postSolve() callback.

Here's the example:

force = ""
world = love.physics.newWorld(0, 200, true)
world:setCallbacks(beginContact, endContact, preSolve, postSolve)

ball = {}
ball.b = love.physics.newBody(world, 400,200, "dynamic")
ball.b:setMass(10)
ball.s = love.physics.newCircleShape(50)
ball.f = love.physics.newFixture(ball.b, ball.s)
ball.f:setRestitution(0.4)    -- make it bouncy
ball.f:setUserData("Ball")
static = {}
static.b = love.physics.newBody(world, 400,400, "static")
static.s = love.physics.newRectangleShape(200,50)
static.f = love.physics.newFixture(static.b, static.s)
static.f:setUserData("Block")

text       = ""   -- we'll use this to put info text on the screen later
persisting = 0    -- we'll use this to store the state of repeated callback calls
end

function love.update(dt)
world:update(dt)

if love.keyboard.isDown("right") then
ball.b:applyForce(1000, 0)
elseif love.keyboard.isDown("left") then
ball.b:applyForce(-1000, 0)
end
if love.keyboard.isDown("up") then
ball.b:applyForce(0, -5000)
elseif love.keyboard.isDown("down") then
ball.b:applyForce(0, 1000)
end

if string.len(text) > 768 then    -- cleanup when 'text' gets too long
text = ""
end
end

function love.draw()
love.graphics.polygon("line", static.b:getWorldPoints(static.s:getPoints()))

love.graphics.print(text, 10, 10)

love.graphics.print(force, 100, 400)
end

function beginContact(a, b, coll)
x,y = coll:getNormal()
text = text.."\n"..a:getUserData().." colliding with "..b:getUserData().." with a vector normal of: "..x..", "..y
end

function endContact(a, b, coll)
persisting = 0
text = text.."\n"..a:getUserData().." uncolliding with "..b:getUserData()
end

function preSolve(a, b, coll)
if persisting == 0 then    -- only say when they first start touching
text = text.."\n"..a:getUserData().." touching "..b:getUserData()
elseif persisting < 20 then    -- then just start counting
text = text.." "..persisting
end
persisting = persisting + 1    -- keep track of how many updates they've been touching for
end

function postSolve(a, b, coll, normalimpulse, tangentimpulse)
force = normalimpulse
end