"Flick" Function Not Working All the Time

Hey guys!

We’re having a problem in making a “flick” function. It works as expected when you do long, drawn out flicks, or when you drag and release. However, if you actually flick, the ball that you’re flicking drops, because the event never ends.

function flick(event) count = 0 if event.phase == "began" then physics.setGravity(0,0) startX = event.x startY = event.y physics.addBody(ball, "dynamic", {friction=1, bounce = 0.3, radius=30, isSleeping = false,filter = {maskBits = 10, categoryBits = 4}}) elseif event.phase == "moved" then --dragging the ball if not x1 then x1 = display.contentCenterX end if not y1 then y1 = display.contentCenterY end x2 = x1 y2 = y1 x1 = event.x y1 = event.y ball.x = event.x ball.y = event.y physics.setGravity(0,0) elseif event.phase == "ended" then --applying force on the ball local a = 3 ball:applyForce(a\*(x1-x2), a\*(y1-y2), ball.x, ball.y) end physics.setGravity(0,18) end

We can’t think of any reason this should be happening. Anyone else experience similar things and/or have a fix to this problem?

Thanks!

There is a lot going on here. I’m assuming you are declaring your “flick” variable somewhere above this function. Using globals, while not specifically terrible, isn’t best practice for Corona development.

You might want to declare the physics body outside of the touch listener, as that can cause a bit of a lag which would cause a problem with your “moved” phase. You can create the physics body for the ball outside the touch listener, and just not do anything with the physics object until the “flick” motion occurs. This can be accomplished by setting a flag of some kind. 

I’d suggest checking out the “Drag” sample project which is provided with all Corona installs. It makes liberal use of the **display.getCurrentStage():setFocus( t ) **API which will help you identify the location of the touch object, regardless of speed of movement.

Thanks for the reply! 

Your idea worked, in that we can now flick the ball as fast as we want. However, when we set the **display.getCurrentStage():setFocus(nil) **when the phase has ended, we can no longer flick the ball as fast as we want. If we leave the ball focused, we have a reset button that becomes unusable. I tried adding a timer, in case the focus is set to nil too quick, and that didn’t do anything. The reset button is still unusable. Any ideas? Code is shown below.

function flick(event) count = 0 if event.phase == "began" then physics.setGravity(0,0) display.getCurrentStage():setFocus(ball) startX = event.x x1, x2 = startX, startX startY = event.y y1, y2 = startY, startY ball.bodyType = "dynamic" elseif event.phase == "moved" then --dragging the bal x2 = x1 y2 = y1 x1 = event.x y1 = event.y ball.x = event.x ball.y = event.y physics.setGravity(0,0) elseif event.phase == "ended" then --applying force on the ball local a = 3 ball:applyForce(a\*(x1-x2), a\*(y1-y2), ball.x, ball.y) end physics.setGravity(0,18) timer.performWithDelay(10, erase) return true end local function erase() display.getCurrentStage():setFocus(nil) end

Thanks!

Normally, with a touch listener that has a setFocus call in it, it’s best practice to use the _display.getCurrentStage():setFocus(nil) _in the “ended” phase. This is considered “safe” as, because the object has the focus, the “ended” phase will always be called.

Yes, I had that. However, the bug comes back where you can’t flick the ball as fast as you want. If you leave out the setFocus(nil), the bug is no longer there. I’m looking for an in between where you can flick the ball as fast as you want, while still being able to use other buttons.

I think you might want to use a comprehensive listener. Take a look at the below example from the docs:

http://docs.coronalabs.com/api/event/touch/index.html#comprehensive

There is a lot going on here. I’m assuming you are declaring your “flick” variable somewhere above this function. Using globals, while not specifically terrible, isn’t best practice for Corona development.

You might want to declare the physics body outside of the touch listener, as that can cause a bit of a lag which would cause a problem with your “moved” phase. You can create the physics body for the ball outside the touch listener, and just not do anything with the physics object until the “flick” motion occurs. This can be accomplished by setting a flag of some kind. 

I’d suggest checking out the “Drag” sample project which is provided with all Corona installs. It makes liberal use of the **display.getCurrentStage():setFocus( t ) **API which will help you identify the location of the touch object, regardless of speed of movement.

Thanks for the reply! 

Your idea worked, in that we can now flick the ball as fast as we want. However, when we set the **display.getCurrentStage():setFocus(nil) **when the phase has ended, we can no longer flick the ball as fast as we want. If we leave the ball focused, we have a reset button that becomes unusable. I tried adding a timer, in case the focus is set to nil too quick, and that didn’t do anything. The reset button is still unusable. Any ideas? Code is shown below.

function flick(event) count = 0 if event.phase == "began" then physics.setGravity(0,0) display.getCurrentStage():setFocus(ball) startX = event.x x1, x2 = startX, startX startY = event.y y1, y2 = startY, startY ball.bodyType = "dynamic" elseif event.phase == "moved" then --dragging the bal x2 = x1 y2 = y1 x1 = event.x y1 = event.y ball.x = event.x ball.y = event.y physics.setGravity(0,0) elseif event.phase == "ended" then --applying force on the ball local a = 3 ball:applyForce(a\*(x1-x2), a\*(y1-y2), ball.x, ball.y) end physics.setGravity(0,18) timer.performWithDelay(10, erase) return true end local function erase() display.getCurrentStage():setFocus(nil) end

Thanks!

Normally, with a touch listener that has a setFocus call in it, it’s best practice to use the _display.getCurrentStage():setFocus(nil) _in the “ended” phase. This is considered “safe” as, because the object has the focus, the “ended” phase will always be called.

Yes, I had that. However, the bug comes back where you can’t flick the ball as fast as you want. If you leave out the setFocus(nil), the bug is no longer there. I’m looking for an in between where you can flick the ball as fast as you want, while still being able to use other buttons.

I think you might want to use a comprehensive listener. Take a look at the below example from the docs:

http://docs.coronalabs.com/api/event/touch/index.html#comprehensive