https://love2d.org/wiki/Tutorial:Physics
I'm not sure if I've misunderstood how to use this function. But I noticed my bounding box was offset by 10+ pixels - or something ?
So I took the basic physics tutorial, and added queryBoundingBox. I use the mouse position during update(dt) and a box of 100,50 size to find objects in the world.
Any found fixture I draw using either the fixture:getBoundingBox(), or the fixture's shape's getPoints() using the fixture's body's getWorldPoints(). You can switch between these by pressing Spacebar.
Where the mouse cursor is, I draw a white box that changes colour pending if it has "overlapped" another object - based on queryBoundingBox.
Then for any "found" object in the queryBoundingBox() I draw that fixture's bounding box of shape's position (press Spacebar to switch between them)
This claims the top grey box is within my queryBoundingBox - but it's so far away. The grey box has its green boundingBox drawn over it.
Is this correct behaviour?
simple main.lua:
Code: Select all
io.stdout:setvbuf('no')
function love.load()
love.physics.setMeter(64) --the height of a meter our worlds will be 64px
world = love.physics.newWorld(0, 9.81*64, true) --create a world for the bodies to exist in with horizontal gravity of 0 and vertical gravity of 9.81
objects = {} -- table to hold all our physical objects
--let's create the ground
objects.ground = {}
objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2) --remember, the shape (the rectangle we create next) anchors to the body from its center, so we have to move it to (650/2, 650-50/2)
objects.ground.shape = love.physics.newRectangleShape(650, 50) --make a rectangle with a width of 650 and a height of 50
objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape); --attach shape to body
--let's create a ball
objects.ball = {}
objects.ball.body = love.physics.newBody(world, 650/2, 650/2, "dynamic") --place the body in the center of the world and make it dynamic, so it can move around
objects.ball.shape = love.physics.newCircleShape(20) --the ball's shape has a radius of 20
objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) -- Attach fixture to body and give it a density of 1.
objects.ball.fixture:setRestitution(0.9) --let the ball bounce
--let's create a couple blocks to play around with
objects.block1 = {}
objects.block1.body = love.physics.newBody(world, 200, 550, "dynamic")
objects.block1.shape = love.physics.newRectangleShape(0, 0, 50, 100)
objects.block1.fixture = love.physics.newFixture(objects.block1.body, objects.block1.shape, 5) -- A higher density gives it more mass.
objects.block2 = {}
objects.block2.body = love.physics.newBody(world, 200, 400, "dynamic")
objects.block2.shape = love.physics.newRectangleShape(0, 0, 100, 50)
objects.block2.fixture = love.physics.newFixture(objects.block2.body, objects.block2.shape, 10)
--initial graphics setup
love.graphics.setBackgroundColor(0.41, 0.53, 0.97) --set the background color to a nice blue
love.window.setMode(650, 650) --set the window dimensions to 650 by 650
local major, minor, revision, codename = love.getVersion()
print(major, minor)
end
mouseposition = {x=0, y=0}
boxcheck = {100, 50}
boxsearch = {1,1,1, 0.25}
boxfound = {1,0,0, 0.25}
found_objects = {}
function love.update(dt)
world:update(dt) --this puts the world into motion
--here we are going to create some keyboard events
if love.keyboard.isDown("right") then --press the right arrow key to push the ball to the right
objects.ball.body:applyForce(400, 0)
elseif love.keyboard.isDown("left") then --press the left arrow key to push the ball to the left
objects.ball.body:applyForce(-400, 0)
elseif love.keyboard.isDown("up") then --press the up arrow key to set the ball in the air
objects.ball.body:setPosition(650/2, 650/2)
objects.ball.body:setLinearVelocity(0, 0) --we must set the velocity to zero to prevent a potentially large velocity generated by the change in position
end
local mx, my = love.mouse.getPosition()
mouseposition.x = mx
mouseposition.y = my
found_objects = search(mx, my)
end
function search(mx, my)
local found = {}
function callback(fixture)
table.insert(found, fixture)
-- keep looking
return true
end
world:queryBoundingBox(mx, my, mx + boxcheck[1], my + boxcheck[2], callback)
return found
end
function love.draw()
love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates
love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())
love.graphics.setColor(0.20, 0.20, 0.20) -- set the drawing color to grey for the blocks
love.graphics.polygon("fill", objects.block1.body:getWorldPoints(objects.block1.shape:getPoints()))
love.graphics.polygon("fill", objects.block2.body:getWorldPoints(objects.block2.shape:getPoints()))
local mx = mouseposition.x
local my = mouseposition.y
local cBox = boxsearch
local drawfixtures = {}
if #found_objects > 0 then
cBox = boxfound
for _, fixture in ipairs(found_objects) do
local topLeftX, topLeftY, bottomRightX, bottomRightY = fixture:getBoundingBox(1)
local shape = fixture:getShape()
local body = fixture:getBody()
if shape:type() == "PolygonShape" then
local points = {shape:getPoints()}
-- calculate the bounding box size
local w = math.abs(topLeftX - bottomRightX)
local h = math.abs(topLeftY - bottomRightY)
local t = {
x = topLeftX,
y = topLeftY,
w = w,
h = h,
points = {body:getWorldPoints(unpack(points))}
}
table.insert(drawfixtures, t)
end
end
end
love.graphics.setColor(cBox)
love.graphics.rectangle("fill", mx, my, unpack(boxcheck))
for _, fixture in ipairs(drawfixtures) do
if not useFixtureShapePoints then
love.graphics.setColor(0.2, 0.8, 0.5, 0.50)
love.graphics.rectangle("fill", fixture.x, fixture.y, fixture.w, fixture.h)
else
love.graphics.setColor(1, 0.2, 0.7, 0.90)
love.graphics.polygon("fill", fixture.points)
end
end
-- draw text
drawtext("Press Space to switch between drawing with getPoints and getBoundingBox", 10, 10)
local txtUseShapePoints = "Using shape:getPoints()"
local txtUseBoundingBox = "Using fixture:getBoundingBox"
local txt = txtUseBoundingBox
if useFixtureShapePoints then
txt = txtUseShapePoints
end
drawtext(txt, 10, 30)
end
function drawtext(text, x, y)
love.graphics.setColor(0,0,0)
love.graphics.print(text, x,y)
love.graphics.setColor(1,1,1)
love.graphics.print(text, x+1, y+1)
end
useFixtureShapePoints = false
function love.keypressed(key)
if key == "space" then
useFixtureShapePoints = not useFixtureShapePoints
end
end