2
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ 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? \$\endgroup\$ – MichaelHouse Jan 1 '14 at 16:51
  • \$\begingroup\$ @Byte56 ok, thanks, I want to to get the force of the collision. \$\endgroup\$ – CharlesL Jan 1 '14 at 17:43
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

You can use normalimpulse in postSolve() callback.

Here's the example:

force = ""
function love.load()
    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.circle("line", ball.b:getX(),ball.b:getY(), ball.s:getRadius(), 20)
    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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.