Heisenbug in my simple Pong game
Posted: Fri Jul 26, 2013 5:25 am
For anyone that does not know what a Heisenbug is, it is a bug that disappears when you attempt to debug it. I finished the Pong tutorial on the HardonCollider github page and played it to realize that there is a bug with the code. What happens is the ball slides up or down the paddle for 1-2 seconds before changing it's direction. What's interesting is the bug disappears if I print out a message whenever the ball touches anything.
Steps to reproduce:
1. Start up pong.love
2. Tap W or S key once
3. Watch as the ball slides up or down the paddle for 1-2 seconds before deflecting
I reproduce the bug 50% of the time whenever I follow those steps above.
pong.love
pong_debug.love
Can anyone confirm if they have the bug too?
Steps to reproduce:
1. Start up pong.love
2. Tap W or S key once
3. Watch as the ball slides up or down the paddle for 1-2 seconds before deflecting
I reproduce the bug 50% of the time whenever I follow those steps above.
pong.love
Code: Select all
HC = require 'hardoncollider'
local text = {}
function on_collide(dt, shape_a, shape_b)
-- determine which shape is the ball and which is not
local other
if shape_a == ball then
other = shape_b
elseif shape_b == ball then
other = shape_a
else -- no shape is the ball. exit
return
end
-- reset on goal
if other == goalLeft then
ball.velocity = {x = 100, y = 0}
ball:moveTo(400,300)
elseif other == goalRight then
ball.velocity = {x = -100, y = 0}
ball:moveTo(400,300)
elseif other == borderTop or other == borderBottom then
-- bounce off top and bottom
ball.velocity.y = -ball.velocity.y
else
-- reflect the ball off the paddle
local px,py = other:center()
local bx,by = ball:center()
ball.velocity.x = -ball.velocity.x
ball.velocity.y = by - py
-- keep the ball at the same speed as before
local len = math.sqrt(ball.velocity.x^2 + ball.velocity.y^2)
ball.velocity.x = ball.velocity.x / len * 100
ball.velocity.y = ball.velocity.y / len * 100
end
--[[text[#text+1] = string.format("%s hit %s",
shape_a.name, shape_b.name)]]
end
function love.load()
Collider = HC(100, on_collide)
ball = Collider:addCircle(400,300, 10)
ball.name = "ball"
leftPaddle = Collider:addRectangle(10,250, 20,100)
leftPaddle.name = "leftPaddle"
rightPaddle = Collider:addRectangle(770,250, 20,100)
rightPaddle.name = "rightPaddle"
ball.velocity = {x = -100, y = 0}
borderTop = Collider:addRectangle(0,-100, 800,100)
borderTop.name = "borderTop"
borderBottom = Collider:addRectangle(0,600, 800,100)
borderBottom.name = "borderBottom"
goalLeft = Collider:addRectangle(-100,0, 100,600)
goalLeft.name = "goalLeft"
goalRight = Collider:addRectangle(800,0, 100,600)
goalRight.name = "goalRight"
end
function love.update(dt)
ball:move(ball.velocity.x * dt, ball.velocity.y * dt)
-- left player movement
if love.keyboard.isDown('w') then
leftPaddle:move(0, -100 * dt)
elseif love.keyboard.isDown('s') then
leftPaddle:move(0, 100 * dt)
end
-- right player movement
if love.keyboard.isDown('up') then
rightPaddle:move(0, -100 * dt)
elseif love.keyboard.isDown('down') then
rightPaddle:move(0, 100 * dt)
end
Collider:update(dt)
end
function love.draw()
ball:draw('fill', 16)
leftPaddle:draw('fill')
rightPaddle:draw('fill')
--[[ print messages
for i = 1,#text do
love.graphics.setColor(255,255,255, 255 - (i-1) * 6)
love.graphics.print(text[#text - (i-1)], 10, i * 15)
end ]]
end
Code: Select all
HC = require 'hardoncollider'
local text = {}
function on_collide(dt, shape_a, shape_b)
-- determine which shape is the ball and which is not
local other
if shape_a == ball then
other = shape_b
elseif shape_b == ball then
other = shape_a
else -- no shape is the ball. exit
return
end
-- reset on goal
if other == goalLeft then
ball.velocity = {x = 100, y = 0}
ball:moveTo(400,300)
elseif other == goalRight then
ball.velocity = {x = -100, y = 0}
ball:moveTo(400,300)
elseif other == borderTop or other == borderBottom then
-- bounce off top and bottom
ball.velocity.y = -ball.velocity.y
else
-- reflect the ball off the paddle
local px,py = other:center()
local bx,by = ball:center()
ball.velocity.x = -ball.velocity.x
ball.velocity.y = by - py
-- keep the ball at the same speed as before
local len = math.sqrt(ball.velocity.x^2 + ball.velocity.y^2)
ball.velocity.x = ball.velocity.x / len * 100
ball.velocity.y = ball.velocity.y / len * 100
end
text[#text+1] = string.format("%s hit %s",
shape_a.name, shape_b.name)
end
function love.load()
Collider = HC(100, on_collide)
ball = Collider:addCircle(400,300, 10)
ball.name = "ball"
leftPaddle = Collider:addRectangle(10,250, 20,100)
leftPaddle.name = "leftPaddle"
rightPaddle = Collider:addRectangle(770,250, 20,100)
rightPaddle.name = "rightPaddle"
ball.velocity = {x = -100, y = 0}
borderTop = Collider:addRectangle(0,-100, 800,100)
borderTop.name = "borderTop"
borderBottom = Collider:addRectangle(0,600, 800,100)
borderBottom.name = "borderBottom"
goalLeft = Collider:addRectangle(-100,0, 100,600)
goalLeft.name = "goalLeft"
goalRight = Collider:addRectangle(800,0, 100,600)
goalRight.name = "goalRight"
end
function love.update(dt)
ball:move(ball.velocity.x * dt, ball.velocity.y * dt)
-- left player movement
if love.keyboard.isDown('w') then
leftPaddle:move(0, -100 * dt)
elseif love.keyboard.isDown('s') then
leftPaddle:move(0, 100 * dt)
end
-- right player movement
if love.keyboard.isDown('up') then
rightPaddle:move(0, -100 * dt)
elseif love.keyboard.isDown('down') then
rightPaddle:move(0, 100 * dt)
end
Collider:update(dt)
end
function love.draw()
ball:draw('fill', 16)
leftPaddle:draw('fill')
rightPaddle:draw('fill')
--[ print messages
for i = 1,#text do
love.graphics.setColor(255,255,255, 255 - (i-1) * 6)
love.graphics.print(text[#text - (i-1)], 10, i * 15)
end
end