Tutorial:PhysicsCollisionCallbacks

Preface

If you do not have a good grasp on love.physics, you should first check out this physics tutorial.

In this tutorial we will create a collision between two objects that calls certain callbacks set by World:setCallbacks.

Tutorial

main.lua setup

I usually start every main.lua with 3 love functions: love.load, love.update, and love.draw

function love.load()
	
end
function love.update(dt)
	
end
function love.draw()
	
end

World setup

Now that we have a framework setup, let's setup a physics world in love.load with newWorld.

Also we will use World:setGravity and World:update.

function love.load()
	--Store the new world in a variable such as "world"
	world = love.physics.newWorld(-800,-600, 800,600)
		--Gravity is being set to 0 in the x direction and 20 in the y direction.
		world:setGravity(0,20)
end

function love.update(dt)
	--Never forget to update your world every frame.
	world:update(dt)
end

Now we want to create a ball and a ground. To do this we will need newBody, newCircleShape, and newRectangleShape.

function love.load()
	--Store the new world in a variable such as "world"
	world = love.physics.newWorld(-800,-600, 800,600)
		--Gravity is being set to 0 in the x direction and 20 in the y direction.
		world:setGravity(0,20)
	ball = {}
		ball.b = love.physics.newBody(world, 400,200, 10,0)
		ball.s = love.physics.newCircleShape(ball.b, 0,0, 50)
		ball.s:setData("Ball")
	static = {}
		static.b = love.physics.newBody(world, 400,400, 0,0)
		static.s = love.physics.newRectangleShape(static.b, -100,-25, 200,50, 0)
		static.s:setData("Block")
end

The balls are there now, but you can't yet see them. Let's draw them. This can be a bit tricky at times to match up the origins of objects.

function love.draw()
	love.graphics.circle("line", ball.b:getX(),ball.b:getY(), ball.s:getRadius())
	local x1,y1, _,_, x3,y3, _,_ = static.s:getBoundingBox()
	local w = x3-x1
	local h = y3-y1
	love.graphics.rectangle("line",
		static.b:getX()-w/2,static.b:getY(),
		w,h, 0)
end

Now we should see a ball fall down and hit a solid rectangle.

World Callbacks

But what if we want more information on the two objects colliding? Now we will use World:setCallbacks to further dissect their collision(s).

First thing we do is set the world callbacks with World:setCallbacks. There are four callbacks for a collision: add, persist, remove, and result.

Add is the callback for every new collision.
Persist is the callback for every collision that is continuing from last frame.
Remove is the callback for any collision that stopped happening since last frame.
Result [do not know what is].
function love.load()
	--Store the new world in a variable such as "world"
	world = love.physics.newWorld(-800,-600, 800,600)
		--Gravity is being set to 0 in the x direction and 20 in the y direction.
		world:setGravity(0,20)
		--Can be almost any function names you want.
		world:setCallbacks(add, persist, rem, result)

Now define each function you just named.

function add(a, b, coll)
	
end

function persist(a, b, coll)
	
end

function rem(a, b, coll)
	
end

function result(a, b, coll)
	
end

These functions are called every time one of the collision actions happen. They pass in two shapes and a collision object. These parameters can also be named to whatever you want. In this tutorial, I chose a, b, and coll.

  • a is the first object in the collision.
  • b is the second object in the collision.
  • coll is the contact object created.

Say we want to print to screen whenever a callback is called. All we have to do is create a variable to store the strings and then append to the string every time a collision action happens.

A list of functions you can use on contacts can be found at the Contact page.

text = ""
function add(a, b, coll)
	text = text..a.." collding with "..b.." at an angle of "..coll:getNormal().."\n"
end

function persist(a, b, coll)
	text = text..a.." touching "..b.."\n"
end

function rem(a, b, coll)
	text = text..a.." uncolliding "..b.."\n"
end

function result(a, b, coll)
	text = text..a.." hit "..b.."resulting with "..coll:getNormal().."\n"
end

And now you know how to use world callbacks!

Finished

Screenshots

Screenshot of the finished product.

main.lua

function love.load()
world = love.physics.newWorld(-800,-600, 800,600)
	world:setGravity(0,20)
	world:setCallbacks(add, persist, rem, result)
	ball = {}
		ball.b = love.physics.newBody(world, 400,200, 10,0)
		ball.s = love.physics.newCircleShape(ball.b, 0,0, 50)
		ball.s:setData("Ball")
	static = {}
		static.b = love.physics.newBody(world, 400,400, 0,0)
		static.s = love.physics.newRectangleShape(static.b, -100,-25, 200,50, 0)
		static.s:setData("Block")
end

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

function love.draw()
	love.graphics.circle("line", ball.b:getX(),ball.b:getY(), ball.s:getRadius())
	local x1,y1, _,_, x3,y3, _,_ = static.s:getBoundingBox()
	local w = x3-x1
	local h = y3-y1
	love.graphics.rectangle("line",
		static.b:getX()-w/2,static.b:getY(),
		w,h, 0)
	love.graphics.print(text,0,12)
end

--Refer to http://love2d.org/wiki/Contact for more information on collision objects
--'coll' is an object created by the collision
--'a' is the first object in the collision and 'b' is the second

text = ""

function add(a, b, coll)
	text = text..a.." collding with "..b.." at an angle of "..coll:getNormal().."\n"
end

function persist(a, b, coll)
	text = text..a.." touching "..b.."\n"
end

function rem(a, b, coll)
	text = text..a.." uncolliding "..b.."\n"
end

function result(a, b, coll)
	text = text..a.." hit "..b.."resulting with "..coll:getNormal().."\n"
end