Detecting finger dragged off of moving object

I just don’t understand what’s the point of dispatchEvent…what exactly does it do in this function:

local function myTouchFunction(event)
  if event.phase == “began” then
 
  elseif event.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
          e.phase = “offTarget”
          e.target:dispatchEvent(e)
    end
    – add your moved code here
 
  elseif event.phase == “offTarget” then
 
  elseif event.phase == “ended” then
 
  elseif event.phase == “cancelled” then
 
  end
end

I don’t get it…what does it do? What role does dispatchEvent have in this function? :confused:

Which part of this code tracks the touch when it moves over the content bounds?

I’m just passing by and haven’t got in details reading each post, so forgive me if this was gone over already, but if the problem is detecting when the touch is off an object, can’t something like this be done?

 

function obj:touch(event) if event.phase == "began" then display.getCurrentStage():setFocus(self); self.isFocus = true; elseif event.phase == "moved" and self.isFocus then if event.x \> self.contentBounds.xMax or event.x \< self.contentBounds.xMin or event.y \> self.contentBounds.yMax or event.y \< self.contentBounds.yMin then print("The touch is outside the object"); else print("Touch is moving"); end elseif self.isFocus then -- only ended and cancel should have remained as phases display.getCurrentStage():setFocus(nil); self.isFocus = nil; end end obj:addEventListener("touch", obj);

The problem was that if the touch has moved over the object’s content bounds, you can’t track it anymore, because it’s not on the object.

As soon as event.x is more than object’s content bounds, it’s not on the object, and therefore won’t be detected.

I’ve solved the problem in my case, by adding a listener to Runtime as well, so that I can still detect touch when it moves over the object’s content bounds.

I have 2 listeners now, one added to the object and the other one added to runtime.

I’m sorry but that’s what setFocus is for (:
Try out my code, you’ll see what I mean (;
When setFocus is set on an object, it won’t let go that object even if the touch is outside of it.

There’s nothing to be sorry about :slight_smile:

I’ve just tried it out, and yeah. Results are the same as my code, only the way you did it is more simple.

I wasn’t familiar with setFocus.

I’ll see which one I’ll use, right now I’m having no problems with either. Maybe I’ll stick with my current code, or maybe I’ll take a step forward and start using setFocus.

So yeah, thanks for this.

I’m glad it helped (; 
Regarding the initial issue of the thread (the ball moving) take into account that if the object moves by itself, the touch won’t be detected anymore if the user also doesn’t move the finger (like if the finger is still, and the object moves away from it).
In that case, you’ll need to do the check inside of an enterFrame event. Store the event.x and y from the touch, and do the contentBounds comparison inside the enterFrame event (even better if those x and y are taken from an object as big as the area the ball will bounce in).

May I just ask something else about the above function that you’ve written?

If display.getCurrentStage():setFocus(self) sets the focus on the current touch object, then what is  self.isFocus = true used for?

self.isFocus is used to avoid going into the “moved” or “ended” phase without having first done a “began” phase (:
Say that you first tap outside of the object, then drag your finger on it. Without it, the moved phase would start (but not a began), and we want to make sure that the object is on :setFocus first (which we do only in the began phase).

As for the “ended”, say your finger is on the screen, the object moves beneath your finger, and you lift your finger. “Ended” would trigger, since the touch has actually ended while on the object, but “moved” and “began” would have never happened (:

So it’s something that you can use or not depending on your necessity. For example you could put the setFocus on began AND on moved, so that no matter if it has just began or if it’s moving on top of the object, it will gain the focus. For example I would do that in the case I have some buttons, and I want them to become inactive if the user drags the finger outside of them, but active if the user drags it inside of them (even from button to button, and not just always with the same button).

Ok, thanks for explaining that. I’ve been using some made up variables for that, and making them true on began phase, to detect if the touch didn’t start on the button.

self.isFocus seems better tho’ so I’ll try to use that in the future.

I still have to do some changes to these functions. I have a little multitouch problem atm. If one finger is touching the jump button, and another finger moves on the D-pad or anywhere else on the screen, the jump button becomes inactive.

I’ve been reading Corona docs…something about “focus on per-object-basis” (setFocus).

after activating multitouch, you need to keep the various touch ids and use them with setFocus.
This will make sure that each object will retain only one touch focus.

 

function obj:touch(event) if event.phase == "began" then display.getCurrentStage():setFocus(self, event.id); self.isFocus = true; elseif event.phase == "moved" and self.isFocus then if event.x \> self.contentBounds.xMax or event.x \< self.contentBounds.xMin or event.y \> self.contentBounds.yMax or event.y \< self.contentBounds.yMin then print("The touch is outside the object"); else print("Touch is moving"); end elseif self.isFocus then -- only ended and cancel should have remained as phases display.getCurrentStage():setFocus(self, nil); self.isFocus = nil; end end obj:addEventListener("touch", obj);

This is the updated code to work with multitouch (:

Lemme try that, to see how it works. Then I gotta dive into it, understand and learn to write such functions myself.

Ha! Works perfectly.

So if I understand this correctly…by adding event.id you can specify which object the touch is happening on. Otherwise it could be any object in the current stage that the touch is currently happening on- not sure if I’m right about this…

“To turn off focus you must specify the object and pass nil for touchID.” ~Corona docs

That’s what you did here, right?:

display.getCurrentStage():setFocus(self, nil);

yep, basically by passing the event.id you tell setFocus that you want focus of that specific touch (referenced by the id), to that specific objects. Afterwards, you tell setFocus that any previous focus of any previous touch specified for the object, must be cancelled.

Ok, thanks!

You’ve helped me speed up the development of my game and helped me learn something that’s gonna be useful when I’ll be programming the rest of the controls :slight_smile:

I’m glad (; 
Good luck with your game!

Erhm…I see it has been a while since this thread got any replies, but I would like to ask something, if anyone still sees it.

What Brent wrote here is exactly what I’ve been trying to do with controls in my game.

I have some directional arrows, and I can put a little larger rectangle object behind them, but I don’t know how do I check if the touch has “moved” to that rectangle. How/ when does some random element recieve a “moved” phase?

Really that has been confusing me for a while. I’ve been looking at the Corona Docs online and there is not much info about “moved” event phase at all. 

This would solve this problem if done correctly, I’m sure.

If anyone still sees this, reply please.

Ok! Found it out myself.

Here’s how to make it work if anyone ever needs to know.

Turns out that you just make a new touch function  for that background object.

function background\_object:touch(event) &nbsp;&nbsp;&nbsp;&nbsp;if(onObject == true and event.phase == "moved") then &nbsp;&nbsp;&nbsp;&nbsp;print("something") &nbsp;&nbsp;&nbsp;&nbsp;end end background\_object:addEventListener("touch", background\_object) &nbsp;

One more thing!

You must add return true in the last line(above the end statement) of the  touch function for the object above the background object.

If not, Corona will detect that the touch has moved, even if it has moved on the object above the background object.

heres an easy way. add this to the moved event phase

if e.x \< e.target.contentBounds.xMin or &nbsp;&nbsp; e.x \> e.target.contentBounds.xMax or &nbsp;&nbsp; e.y \< e.target.contentBounds.yMin or &nbsp;&nbsp; e.y \> e.target.contentBounds.yMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.phase = "offTarget" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.target:dispatchEvent(e) end

then create an offTarget phase

if event.phase == "offTarget" then &nbsp; end

so the complete code would be something like this

local function myTouchFunction(event) &nbsp; if event.phase == "began" then &nbsp; &nbsp; elseif event.phase == "moved" then &nbsp;&nbsp;&nbsp; if e.x \< e.target.contentBounds.xMin or &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.x \> e.target.contentBounds.xMax or &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.y \< e.target.contentBounds.yMin or &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.y \> e.target.contentBounds.yMax then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.phase = "offTarget" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.target:dispatchEvent(e) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; -- add your moved code here &nbsp; &nbsp; elseif event.phase == "offTarget" then &nbsp; &nbsp; elseif event.phase == "ended" then &nbsp; &nbsp; elseif event.phase == "cancelled" then &nbsp; &nbsp; end end

Ah, yes I thought of taking advantage of contentBounds, but I screwed up…

I was checking if event.phase moved to exact contentBounds, not if it moved over them.

I was using = instead of <.

I thought that I can’t use contentBounds to check touch moved position, so I just used used the background rectangle.

But yeah, thanks for this. Will be useful in the future.

Just tried using contentBounds to check when the touch has moved off of the object and…no it just doesn’t work for me.

It detects when the touch has moved, but it doesn’t detect if the touch has moved over the content bounds. It does nothing, even if I just try to print out something.

It might be that I’m doing something wrong. I don’t really understand what dispatchEvent does…I looked it up at Corona Docs, and it doesn’t really tell me much (again)…feels like I’m reading some alien language.

Maybe I should just stick to rectangle method for now.

(I’ve learnt everything I know about coding by trying stuff out, not by reading docs that are written in professional words that I have no idea what they mean. I just sometimes use docs to check syntax)

EDIT:

Ok, I’ve been playing around with code a bit more, and now I at least know why it doesn’t detect touch if it has moved over the contentBounds- because at that point, touch is not on the object anymore, and it’s not being tracked anymore.

Now I’ve got to figure out how to detect touch when it has moved off of the object. I’m guessing it has something to do with  dispatchEvent , but yeah…I don’t know what  dispatchEvent  does, so I’m gonna try to stare at those docs for a few more hours and hopefully learn something.