Tutorial:PhysicsCollisionCallbacks
Contents
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)
--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)
--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)
--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
main.lua
function love.load()
world = love.physics.newWorld(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