Cancelling a touch event

I searched around and didn't find what I was looking for.

So I'm dragging an object around the screen and it runs into something that it cannot pass through. If I keep dragging and get far enough away, the object eventually teleports to my location skipping what blocked it.

I'm only getting "moved" events from the event handler. I need someway to force the event to end, beyond simply returning true or to prevent the teleport.

Thoughts?

Thanks
Rob

This isn't quite what you are asking and may or may not be a viable option, but could you have a check for how far away the touch is from the object and end the event that way?

Have you tried to have exclusive events to that object using setFocus so that it does not jump into and from hyperspace ;)

Other way would be to have a hitTest on every mouseMove to check if the current position is within the bounds of the object that you want to and if not then you can cancel the drag if required.

I tried to limit the value of target.x0 and .y0 to 5 pixels, but that didn't do much.

I know where the problem lies. I'm just not sure how to fix it yet.

Hey, Rob @robmiracle, have you found a solution to this problem? I'd like to be able to cancel a touch event too, but I haven't found the way to do it. I'd very much like to hear how to solve this if possible at all.

Naomi

How are you dragging the object?

If you are getting listener events when you move the object, you must be setting object.x/object.y to make it move. To stop the object from being moved, you could add a temporary property (flag) to the object that indicates it shouldn't be moved. Your code would check this flag for every move event. You clear this property at the ended or began phase.

Thank you, Tom, for the tip. I've gotten an advice on this thread too.

I'll try using a flag and trigger the cancellation via runtime listener. Hopefully, setting focus to nil would simply cancel the touch event:

1
2
display.getCurrentStage():setFocus(nil);
myObject.isFocus = false;

@Naomi,

Setting focus to nil doesn't stop the event. All it does is allow other objects to get the touch event if the touch moves off the object. If you setFocus to nil and you move off the object, it will never receive a ended event for that object.

The best way to handle the problem is keep the focus on the object (so you get an ended event) and set a custom flag in the object so you can ignore the moved events. You clear the focus on the ended event.

@Tom, thank you so much for the advice and detailed explanation as to what happens when the setFocus is nilled.

I'd like to know if there's a harm in not reaching the ended event. When I set setFocus to nil, I also trigger things that should happen when the touch reaches "end" (or "cancelled") state. It appears that the same object can be touched again and respond to "began" phase (but I need to test this thoroughly to ensure it does.) If the object can be touched again, and can trigger "began" phase without an issue, nilling focus would be a real good solution for me. Hmmm... when the object is touched again, does it trigger "cancelled" event from the previous touch? If it does, this is actually the most perfect solution for me.

What I'm trying to address is a bug that isn't too easy to reproduce, but can happen every now and then. The problem is, even when the finger is lifted off the screen (and off of the object), my game sometimes does not register that the touch event has ended. When this happens, the game eventually comes to a freezing point. Hard exit is the only option at that point.

In fact, if there's a way to tell the game that the touch is cancelled upon specific flag/trigger and properly reaches the "cancelled" state even when finger is still touching the object, that would help me set up a very good work around to my problem. (And nilling focus appears to work the way I hoped it would so far.)

That said, the best solution would be, for the device/simulator to always and accurately detect the end of the touch event. If it can truly reach the end state when nothing is touching the screen, I wouldn't have to find the workaround to force the cancellation event.

Is there a built in function that I can fire off to force the object to register the fact the touch has already been ended? When the screen is no longer being touched, I really want my object to register that it is not being touched....

Naomi

I'm trying something similar but if you drag and run into something you probably should be able to go the other direction in the same move so I'm thinking I dont need to stop the event as much as prevent teleports

Rob

@robmiracle and @Naomi,

When you wish to cancel the touch (object collides with something or whatever), have you tried using the "dispatchEvent()" command to "force send" and "ended" phase to the object? If you haven't used this command before or aren't too familiar with it (I think alot of people aren't even aware that it exists), it's one of the rare Corona gems that can solve a multitude of issues with one line. Basically, you can "send" any event of any type(name) to an object that has a listener. Furthermore, you're not even limited by Corona's built-in parameters; you can even do something like this:

obj:dispatchEvent( { name="touch", phase="off" } )

You'll notice that "off" is not a standard Corona touch phase condition, but you can still send it and listen for that value in the object's listener routine... or you can, obviously, send a standard phase value like "ended" and Corona will treat that exactly the same as if the user's finger lifted off the screen.

Another example with even more customization...

1
2
3
4
5
6
7
8
9
local function myListener( event )
  if ( event.condition = "stop" ) then
    --do something!
  end
end
 
local obj = --(display object, i.e a button)
obj:addEventListener( "tap", myListener )
obj:dispatchEvent( { name="tap", target=obj, condition="stop" } )

Hey, Brent @IgnisDesign, thank you so much for the sample code, showing how the syntax for dispatchEvent works. This is an awesome command to keep in our backpocket. I saw the mention of this command here yesterday, but I failed to execute it properly. I should've dug further.

Thanks again!!

Naomi

The fact that you can send an event to an object doesn't affect any previous events pending for the object and may confuse your logic if you're not careful.

Lets say your are dragging an object and you get "moved" events. At some point you hit something and you dispatch a "ended" event to the object. When the user removes his/her finger from the object, it receives another "ended" event (from the event that gave you the "began" and "moved" phases). That just means you need extra code to handle that situation.

I agree that dispatchEvent can be useful, but you need to understand how things work (or not working) before throwing another variable into the mix.

BTW, the "cancelled" event phase does not indicate that you can somehow cancel an ongoing event. It is an iOS event that occurs when something interrupts your app, e.g., user answers a phone call in the middle of playing your game.

Thank you for clarifying this Tom! I assumed that dispatching an "ended" event would effectively end the entire event series for that particular touch (or tap). I will go back and check my usage of this command; I probably already put in flags or other code which absolutely puts an end to the entire motion, but it's nice to know how this API behaves internally.

Brent Sorrentino
Ignis Design

Thank you, Tom, for the detailed info. It's really good to know that dispatching event does not directly change the state of pending event.

That said, I dispatch "cancelled" phase (rather than "ended"), and with the added flag & code, I get the result I want. (I'd need to test this extensively, though, to confirm.)

Is there anything wrong with dispatching "cancelled" phase? Should I avoid sending "cancelled" phase, but instead, send some other custom phase?? I'd like to dispatch "cancelled" phase if there's no more harm in doing so than dispatching "ended" phase.

Thanks again.

Naomi

There is nothing that would affect Corona by sending "cancelled" phase, but I would use a different phrase just to show where the event came from. You could get a real "cancelled" event at some point which could cause a debugging nightmare. Maybe called it "iCancelled" :)

@Tom, thank you for the suggestion. It sounds like I should not dispatch "cancelled" -- "iCancelled" does sound good to me.

Thanks again!
Naomi

views:2995 update:2012/2/12 11:34:30
corona forums © 2003-2011