Problem with click holding

Hi all. I am having troubles trying to get this to work properly on devices. 

Expected outcome. 

  • User clicks on an object 
  • If they hold the button down a progress bar appears. 
  • when the progress reaches 99 it performs an action.
  • If the user lifts their finger or moves off of the object then it cancels the progress bar and resets the values.

Outcome.

All is well on the simulator however on the device what happens is that as soon as you click down it automatically cancels. I am assuming this is because the touch is pixel perfect and the slightest movement of your finger cancels it :frowning: Does anyone have an idea how I can fix this. 

here is my code. 

local function removeProgressSquare() display.remove( holdAction.rectOuter ) holdAction.rectOuter = nil display.remove( holdAction.rectInner ) holdAction.rectInner = nil holdAction.percentage = nil holdAction = nil end local function updateProgressSquare() if holdAction.percentage == 99 then holdAction.percentage = 1 holdAction.rectInner.width = 1 rewardlets.R1() data.player.miningLevel.level = data.player.miningLevel.level + 1 print(holdAction.percentage) else holdAction.percentage = holdAction.percentage + 1 holdAction.rectInner.width = holdAction.rectInner.width + 1 print(holdAction.percentage) end end local function updateSkill(event) if event.phase == "began" then Runtime:addEventListener("enterFrame", updateProgressSquare) if holdAction == nil then holdAction = {} holdAction.percentage = 0 holdAction.x = event.xStart holdAction.y = event.yStart holdAction.rectOuter = display.newRect( 0,0, 100, 20) holdAction.rectOuter.anchorX = 0; holdAction.rectOuter.anchorY = 0 holdAction.rectOuter.x = holdAction.x - 50; holdAction.rectOuter.y = holdAction.y - 100 holdAction.rectInner = display.newRect( 0, 0, 1, 18 ) holdAction.rectInner.anchorX = 0; holdAction.rectInner.anchorY = 0 holdAction.rectInner.x = holdAction.rectOuter.x + 1; holdAction.rectInner.y = holdAction.rectOuter.y + 1 holdAction.rectInner:setFillColor(rgb.getColorFromName("purple")) end elseif event.phase == "moved" or event.phase == "ended" then if holdAction == nil then else removeProgressSquare() Runtime:removeEventListener("enterFrame", updateProgressSquare) end end return true end local object = {} object.asset = display.newImage(asset, x \* 64 - 32, y \* 64 - 32, true ) object.asset.width = 124; object.asset.height = 124; object.gridLocation = {x = x, y = y} object.asset:addEventListener("touch", updateSkill ) self.mapLayers:insert(object.asset) return self

You can compare the absolute values of event.x and event.y with event.xStart and event.yStart within your ‘moved’ phase, to check how many pixels the user moved their finger. If they move it more than say 5 or 10 pixels in the X or Y direction, then cancel the progress bar, otherwise do nothing.

Any time you have something being “held” you need to include a buffer dead zone.  2 examples:

  1. made an RC car with an arduino and the controller signal on the forward/reverse control fluctuated ± 2 or 3 units (range was say 1398 to 1403) so I had to create a “dead zone” from say 1395 to 1405 so that the car wouldn’t freak out.

  2. working on a game right now with corona where the tilt of the phone moves the player.  When the phone is flat, accelerometer is at 0 but I don’t want the player moving around like crazy, so I’ve set it to if the tilt is beyond ± 5 or so, THEN the player starts moving.

In my cases, I’ve set up the code to look for exact values but Nick Sherman’s idea of using absolute values would be a better approach for your situation.

Thanks for the advice. I added annother else if into the listener and added the following checks. This now works perfectly. Thanks so much for your help everyone.

 elseif event.phase == "moved" then if holdAction ~= nil then if event.x \< holdAction.x - 32 or event.x \> holdAction.x + 32 or event.y \< holdAction.y - 32 or event.y \> holdAction.y + 32 then removeProgressSquare() Runtime:removeEventListener("enterFrame", updateProgressSquare) end end

You can compare the absolute values of event.x and event.y with event.xStart and event.yStart within your ‘moved’ phase, to check how many pixels the user moved their finger. If they move it more than say 5 or 10 pixels in the X or Y direction, then cancel the progress bar, otherwise do nothing.

Any time you have something being “held” you need to include a buffer dead zone.  2 examples:

  1. made an RC car with an arduino and the controller signal on the forward/reverse control fluctuated ± 2 or 3 units (range was say 1398 to 1403) so I had to create a “dead zone” from say 1395 to 1405 so that the car wouldn’t freak out.

  2. working on a game right now with corona where the tilt of the phone moves the player.  When the phone is flat, accelerometer is at 0 but I don’t want the player moving around like crazy, so I’ve set it to if the tilt is beyond ± 5 or so, THEN the player starts moving.

In my cases, I’ve set up the code to look for exact values but Nick Sherman’s idea of using absolute values would be a better approach for your situation.

Thanks for the advice. I added annother else if into the listener and added the following checks. This now works perfectly. Thanks so much for your help everyone.

 elseif event.phase == "moved" then if holdAction ~= nil then if event.x \< holdAction.x - 32 or event.x \> holdAction.x + 32 or event.y \< holdAction.y - 32 or event.y \> holdAction.y + 32 then removeProgressSquare() Runtime:removeEventListener("enterFrame", updateProgressSquare) end end