The code below:
-
places two white circles on the screen
-
upon touch input draws a white line (free-hand style)
-
when the line hits one of the balls, then that ball changes its color from white to red
-
as soon as both balls are hit by the line, then both balls and the line disappear and the game loop begins again
This code, as it currently stands, works, however, when I turn the drawLineAndCheckIfBallsAreHit function by replacing the line
function drawLineAndCheckIfBallsAreHit(event)
with
local function drawLineAndCheckIfBallsAreHit(event)
then the code no longer recognizes when the line hits one of the balls. Instead, you can draw lines across either ball without that ball ever turning red.
Would someone be able to explain why the code no longer works when the drawLineAndCheckIfBallsAreHit function is turned into a local function? I understand it has to do with scope but I can’t figure out what exactly is going on. It seems to me that the code should still work, even with that function being a local function.
display.setStatusBar(display.HiddenStatusBar) local numberOfBallsHit = 0 local ballsHit = {} local ball1Hit = false local ball2Hit = false local levelHasEnded = false local gameLoopSpeed = 200 local drawLineAndCheckIfBallsAreHit, linePoints, line = display.newGroup(), {}, nil local function InitializeBalls() ball1 = display.newCircle(200,100, 30) ball1.name = "ball1" ball1:setFillColor(1,1,1) ball1:addEventListener("touch", drawLineAndCheckIfBallsAreHit) ball2 = display.newCircle(400,300, 30) ball2.name = "ball2" ball2:setFillColor(1,1,1) ball2:addEventListener("touch", drawLineAndCheckIfBallsAreHit) end local function distanceBetweenTwoPoints( ax, ay, bx, by ) local width, height = bx-ax, by-ay return (width\*width + height\*height)^0.5 end function drawLineAndCheckIfBallsAreHit(event) if (event.phase == "began") then linePoints = {x=event.x, y=event.y} phaseHasBegun = true return true elseif phaseHasBegun then if (event.phase == "moved") then if (distanceBetweenTwoPoints( linePoints.x, linePoints.y, event.x, event.y ) \> 1) then linePoints = {x=event.x, y=event.y} if (line==nil) then line = display.newLine(event.xStart, event.yStart, linePoints.x, linePoints.y) line:setStrokeColor (1,1,1) line.strokeWidth = 20 else line:append(linePoints.x, linePoints.y) if event.target then -- event.target = nil for as long as line hasn't hit any balls if (event.target.name=="ball1" and ball1Hit==false) then ball1:setFillColor(1,0,0) timer.performWithDelay(10, ball1:removeEventListener("touch", drawLineAndCheckIfBallsAreHit)) ball1Hit = true numberOfBallsHit = numberOfBallsHit +1 table.insert(ballsHit, 1) end if (event.target.name=="ball2" and ball2Hit==false) then ball2:setFillColor(1,0,0) timer.performWithDelay(10, ball2:removeEventListener("touch", drawLineAndCheckIfBallsAreHit)) ball2Hit = true numberOfBallsHit = numberOfBallsHit +1 table.insert(ballsHit, 2) end end end end else -- touch has ended; now remove line so a new line can be drawn phaseHasBegun = false display.remove(line) linePoints, line = {}, nil end return true end return false end local function endLevel() timer.performWithDelay(10, Runtime:removeEventListener("touch", drawLineAndCheckIfBallsAreHit)) display.remove(ball1) ball1=nil display.remove(ball2) ball2=nil display.remove(line) end local function initializeNextLevel() numberOfBallsHit = 0 ballsHit = {} ball1Hit = false ball2Hit = false levelHasEnded = false linePoints, line = {}, nil InitializeBalls() Runtime:addEventListener( "touch", drawLineAndCheckIfBallsAreHit ) end local function gameLoop() if numberOfBallsHit==2 and levelHasEnded==false then endLevel() levelHasEnded = true numberOfBallsHit = 0 end if levelHasEnded==true then timer.performWithDelay(2000, initializeNextLevel) levelHasEnded = false end end --Start game InitializeBalls() Runtime:addEventListener( "touch", drawLineAndCheckIfBallsAreHit) timer.performWithDelay(gameLoopSpeed, gameLoop,0)
Same code again, just pasted into this forum using a different method, hoping for better formatting. Apologies but I seems to get weird formatting when I paste code into this forum.
[lua]display.setStatusBar(display.HiddenStatusBar)
local numberOfBallsHit = 0
local ballsHit = {}
local ball1Hit = false
local ball2Hit = false
local levelHasEnded = false
local gameLoopSpeed = 200
local drawLineAndCheckIfBallsAreHit, linePoints, line = display.newGroup(), {}, nil
local function InitializeBalls()
ball1 = display.newCircle(200,100, 30)
ball1.name = “ball1”
ball1:setFillColor(1,1,1)
ball1:addEventListener(“touch”, drawLineAndCheckIfBallsAreHit)
ball2 = display.newCircle(400,300, 30)
ball2.name = “ball2”
ball2:setFillColor(1,1,1)
ball2:addEventListener(“touch”, drawLineAndCheckIfBallsAreHit)
end
local function distanceBetweenTwoPoints( ax, ay, bx, by )
local width, height = bx-ax, by-ay
return (width*width + height*height)^0.5
end
function drawLineAndCheckIfBallsAreHit(event)
if (event.phase == “began”) then
linePoints = {x=event.x, y=event.y}
phaseHasBegun = true
return true
elseif phaseHasBegun then
if (event.phase == “moved”) then
if (distanceBetweenTwoPoints( linePoints.x, linePoints.y, event.x, event.y ) > 1) then
linePoints = {x=event.x, y=event.y}
if (line==nil) then
line = display.newLine(event.xStart, event.yStart, linePoints.x, linePoints.y)
line:setStrokeColor (1,1,1)
line.strokeWidth = 20
else
line:append(linePoints.x, linePoints.y)
if event.target then – event.target = nil for as long as line hasn’t hit any balls
if (event.target.name==“ball1” and ball1Hit==false) then
ball1:setFillColor(1,0,0)
timer.performWithDelay(10, ball1:removeEventListener(“touch”, drawLineAndCheckIfBallsAreHit))
ball1Hit = true
numberOfBallsHit = numberOfBallsHit +1
table.insert(ballsHit, 1)
end
if (event.target.name==“ball2” and ball2Hit==false) then
ball2:setFillColor(1,0,0)
timer.performWithDelay(10, ball2:removeEventListener(“touch”, drawLineAndCheckIfBallsAreHit))
ball2Hit = true
numberOfBallsHit = numberOfBallsHit +1
table.insert(ballsHit, 2)
end
end
end
end
else – touch has ended; now remove line so a new line can be drawn
phaseHasBegun = false
display.remove(line)
linePoints, line = {}, nil
end
return true
end
return false
end
local function endLevel()
timer.performWithDelay(10, Runtime:removeEventListener(“touch”, drawLineAndCheckIfBallsAreHit))
display.remove(ball1)
ball1=nil
display.remove(ball2)
ball2=nil
display.remove(line)
end
local function initializeNextLevel()
numberOfBallsHit = 0
ballsHit = {}
ball1Hit = false
ball2Hit = false
levelHasEnded = false
linePoints, line = {}, nil
InitializeBalls()
Runtime:addEventListener( “touch”, drawLineAndCheckIfBallsAreHit )
end
local function gameLoop()
if numberOfBallsHit==2 and levelHasEnded==false then
endLevel()
levelHasEnded = true
numberOfBallsHit = 0
end
if levelHasEnded==true then
timer.performWithDelay(2000, initializeNextLevel)
levelHasEnded = false
end
end
–Start game
InitializeBalls()
Runtime:addEventListener( “touch”, drawLineAndCheckIfBallsAreHit)
timer.performWithDelay(gameLoopSpeed, gameLoop,0)
[/lua]