From the Forum to the rescue! Check out this forum post for a bit of info on onscreen touch logic.
“A lot of people encounter this issue and, just like almost every other dilemma, the Corona community has come up with a great solution…”
I’m on it!
I’m adding the event listener like this;
autoTurret:addEventListener("touch", autoTurretTouchListener)
And if I start the touch inside the object it fires “began”, and when I move out of the object while pressed I get a lot of “moved”. And once I’m out of the object bounds I get no more updates, if I release the touch I see nothing, the last time it entered the listener it was “moved”. What are we doing different?
Setting bounding properties for the touch listener is the best way to accomplish what you’re looking for IMO. Check out that forum post for some sample code to get started.
I copy pasted the exact code to my project and when I run it I get the same old results. e.phase never becomes “offTarget”
I tried the same method myself prior but as soon as the mouse leaves the content bounds, the listener stops getting further updates so it never knows the event.x is actually out. Is there any chance something else is interfering with touch listeners?
Did you declare the object which should demonstrate the contentBounds properties? Can you post your own code so we can take a look?
Here is the code that seems to work for some but not for me;
local button = display.newCircle(320,500, 150) button:setFillColor(255,0,0 ) local function buttonClick() button:setFillColor(55,10,0 ) end local function buttonRelease() button:setFillColor(255,0,0 ) end local function buttonPressed(e) if e.phase == "began" then buttonClick(e.target) elseif e.phase == "moved" then if e.x \< e.target.contentBounds.xMin or e.x \> e.target.contentBounds.xMax or e.y \< e.target.contentBounds.yMin or e.y \> e.target.contentBounds.yMax then print("Its out") e.phase = "offTarget" e.target:dispatchEvent(e) end elseif e.phase == "offTarget" then buttonRelease() print("It ran off the button") elseif e.phase == "ended" then buttonRelease() print("It ended") elseif e.phase == "cancelled" then buttonRelease() print("It canceled") end end button:addEventListener("touch",buttonPressed)
Try putting the buttonRelease() function call inside the contentBounds logic call inside the touch listener.
That was a mouthful. Try this and let us know what happens:
if e.x \< e.target.contentBounds.xMin or e.x \> e.target.contentBounds.xMax or e.y \< e.target.contentBounds.yMin or e.y \> e.target.contentBounds.yMax then print("Its out") buttonRelease() --e.phase = "offTarget" e.target:dispatchEvent(e) end
You need to “return true” in your call as well otherwise it keeps going.
@Panc software, I tried it and it is the same result, the last execution of ‘buttonPressed’ function gets “event.phase == moved” and nothing else once touch is outside.
@Christopher Bishop, I tried it with and without returning true after your post. The only difference I see is that if I return true, my global touch listener won’t fire if I press inside the object. Otherwise it’s the same issue.
Ok so little confused here, you have a “global” touch handler and a local one attached to your button?
Yes, I have a runtime touch listener but I tried removing it entirely, the result was the same.
Edit: I said yes earlier but I guess the correct answer should have been no. I don’t have them both on the same object. I have a touch listener for each turret, and a runtime touch listener.
local function onScreenTouch(event) if isGamePaused == true then return end if event.phase == "began" then mouseX = event.x mouseY = event.y startShooting() elseif ( event.phase == "ended" or event.phase == "cancelled" ) then stopShooting() end if event.phase == "moved" then mouseX = event.x mouseY = event.y end return true end
I also tried not returning true, the result was the same with my button touch listener.
the code was meant for touch on objects not global but could be modified
Okay, I just learned about setFocus() and it was just what I needed! This works like a charm, does exactly what I wanted;
local function autoTurretTouchListener(e) if(isGamePaused == false) then local turret = e.target if (e.phase == "began") then display.getCurrentStage():setFocus( e.target, e.id ) if(turret.shootingTimer == nil) then turret.shootingTimer = timer.performWithDelay(turret.fireRate, function() turret:spawnBall() end, 0) end if(isMainTurretShooting == false) then timer.performWithDelay(1, function() stopShooting() end, 1) end timer.resume(turret.shootingTimer) elseif e.phase == "ended" or e.phase == "cancelled" then display.getCurrentStage():setFocus( nil, e.id ) if(turret.shootingTimer ~= nil) then timer.pause(turret.shootingTimer) end elseif e.phase == "cancelled" then if(turret.shootingTimer ~= nil) then timer.pause(turret.shootingTimer) end turret.isShooting = false display.getCurrentStage():setFocus( nil ) elseif e.phase == "moved" then --if touch is moved outside of turret if e.x \< e.target.x - e.target.width/2 or e.x \> e.target.x + e.target.width/2 or e.y \< e.target.y - e.target.height/2 or e.y \> e.target.y + e.target.height/2 then if(turret.shootingTimer ~= nil) then timer.pause(turret.shootingTimer) end end end end end