Detecting finger dragged off of moving object

Ok so I tried doing that but if I dragged my finger off of the bubble nothing would happen (canceled), but if I removed my finger, it would disappear (ended). 

Here is the code.

function gameStart(event) if event.phase == "began" then if start == false then -- get stage and call 'setFocus()' method local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true bubble:applyLinearImpulse( -200, -500 , bubble.x+150, bubble.y+150 ) title:removeSelf() instructions:removeSelf() start = true local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true end elseif bubble.isFocus then if event.phase == "ended" or event.phase == "cancelled" then local stage = display.getCurrentStage() stage:setFocus( nil ) bubble:removeSelf() end end end

Hi @SummitTech,

Just a few quick comments on phases:

  1. “cancelled” is not really an event that gets triggered by the user. It generally happens only if the OS itself cancels the process, i.e. something interrupts the process.

  2. you won’t get an “ended” phase by moving a touch off the object (as in, sliding your touch outside the object’s bounds). “ended” is triggered when you lift your touch off an object, but that touch point is still within the object bounds.

  3. to sense a touch sliding off an object, you might try setting up some kind of background object (behind the other object) or stage listener, and then set up a flag like “onObject” as true when the touch is on the object. Then, if the background element receives a “moved” phase while that flag is true, you can assume the touch came from the object and then moved onto the background (thus, what you need).

Hope this helps,

Brent

Thanks for the help Brent! I’ll let you know if it works!

Ok I don’t know if I am doing something wrong (or forgetting to do something), or if the program just doesn’t work.

Here is a basic overview of what I am trying to accomplish.

User touches object and it starts to move around the screen.

The player must keep their finger on the object at all times or they lose.

Here is part of my code

function loseGame(event) bubble:removeSelf() start = false end function bgF(event) if start == true then if event.phase == "moved" and event.phase == "began" then loseGame() end end end function gameStart(event) if event.phase == "began" then if start == false then -- get stage and call 'setFocus()' method local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true bubble:applyLinearImpulse( -200, -500 , bubble.x+150, bubble.y+150 ) title:removeSelf() instructions:removeSelf() start = true local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true --Game functions function hitWall(event) bubble:setLinearVelocity( 0, 0 ) chooseLocation() end function chooseLocation(event) m = (math.random(24)) move() end function move(event) end end elseif bubble.isFocus then if event.phase == "ended" or event.phase == "cancelled" then local stage = display.getCurrentStage() stage:setFocus( nil ) loseGame() end end end bubble:addEventListener("touch", gameStart) bg:addEventListener("touch",bgF)

Thanks a ton for everyone’s help and support!

function loseGame(event) bubble:removeSelf() start = false end function bgF(event) if start == true then if event.phase == "moved" and event.phase == "began" then loseGame() end end end function gameStart(event) if event.phase == "began" then if start == false then get stage and call 'setFocus()' method local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true title:removeSelf() instructions:removeSelf() start = true local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true --Game functions function hitWall(event) bubble:setLinearVelocity( 0, 0 ) chooseLocation() end function chooseLocation(event) m = (math.random(24)) move() end function move(event) end end elseif bubble.isFocus then if event.phase == "ended" or event.phase == "cancelled" then local stage = display.getCurrentStage() stage:setFocus( nil ) loseGame() end end hitWall() end end bubble:addEventListener("touch", gameStart)

There you go! Tided it up a bit! Hope that helps.

Does anyone have any clue on how to do this? Not to rush anyone but its kind of important.

Thanks!

Bump :slight_smile:

I could use some help about now

Your code is really hard to read.  Maybe you could indent things so we can see where functions really begin and end.  

function loseGame(event) bubble:removeSelf() start = false end function bgF(event) if start == true then if event.phase == "moved" and event.phase == "began" then loseGame() end end end function gameStart(event) if event.phase == "began" then if start == false then get stage and call 'setFocus()' method local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true title:removeSelf() instructions:removeSelf() start = true local stage = display.getCurrentStage() stage:setFocus( bubble ) bubble.isFocus = true --Game functions function hitWall(event) bubble:setLinearVelocity( 0, 0 ) chooseLocation() end function chooseLocation(event) m = (math.random(24)) move() end function move(event) end end elseif bubble.isFocus then if event.phase == "ended" or event.phase == "cancelled" then local stage = display.getCurrentStage() stage:setFocus( nil ) loseGame() end end hitWall() end end bubble:addEventListener("touch", gameStart)

There you go! Tided it up a bit! Hope that helps.

Any help?

I’m stuck at the moment :confused:

I don’t see where your function bgf() is being called anywhere, but if you do:

if event.phase == “moved” and event.phase == “began” then

You can’t have an event.phase be both “moved” and “begain” at the same time.  This will always evaluate to false.

I don’t know what this line of code is and if it’s a comment that’s not commented out, your app will be generating errors:
 

get stage and call ‘setFocus()’ method

 

You repeat these three lines of code, though it should have no effect:

local stage = display.getCurrentStage()

stage:setFocus( bubble )

bubble.isFocus = true

Your function move() does nothing.

You don’t handle a the event.phase == “moved” in your gameStart() function, which is your bubble’s event handler.

You blindly remove your instructions and title every time bubble is touched.  You need to test to make sure they exist and have not already been removed before you try and remove them.  You also are not setting the values to nil when you are done removing them.  Consider:

    if title and title.removeSelf then

         title:removeSelf()

         title = nil

    end

This makes sure that title exists, it’s still a display object and properly cleans it up.

Finally touch events generate a minimum of two events:  a “began” event and an “ended” event.  You will also get multiple “moved” events.  So lets say you touch the balloon and move it a bit and let up, your hitWall() function is going to get called once for every one of those events.  I’m not sure that’s what you want to happen.

Finally your function should probably be doing:    return true

at the end to keep the event from going on to other display objects.

Any help?

I’m stuck at the moment :confused:

I don’t see where your function bgf() is being called anywhere, but if you do:

if event.phase == “moved” and event.phase == “began” then

You can’t have an event.phase be both “moved” and “begain” at the same time.  This will always evaluate to false.

I don’t know what this line of code is and if it’s a comment that’s not commented out, your app will be generating errors:
 

get stage and call ‘setFocus()’ method

 

You repeat these three lines of code, though it should have no effect:

local stage = display.getCurrentStage()

stage:setFocus( bubble )

bubble.isFocus = true

Your function move() does nothing.

You don’t handle a the event.phase == “moved” in your gameStart() function, which is your bubble’s event handler.

You blindly remove your instructions and title every time bubble is touched.  You need to test to make sure they exist and have not already been removed before you try and remove them.  You also are not setting the values to nil when you are done removing them.  Consider:

    if title and title.removeSelf then

         title:removeSelf()

         title = nil

    end

This makes sure that title exists, it’s still a display object and properly cleans it up.

Finally touch events generate a minimum of two events:  a “began” event and an “ended” event.  You will also get multiple “moved” events.  So lets say you touch the balloon and move it a bit and let up, your hitWall() function is going to get called once for every one of those events.  I’m not sure that’s what you want to happen.

Finally your function should probably be doing:    return true

at the end to keep the event from going on to other display objects.

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)     if(onObject == true and event.phase == "moved") then     print("something")     end end background\_object:addEventListener("touch", background\_object)  

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.

thats the way i started learning years ago. maybe if you show me some code i can help. the code i posted above works as is for me. dispatchEvent is a way of creating your own event. like enterFrame, userInput, touch, … in the code above theres an eventListener for a touch event on the circle. when i dispatch my event what im doing is changing the event.phase and im resending it back to the circle as a touch event. You can completely make your own event and dispatch it to an object or to the Runtime. all you need to do is create a variable for a table and inside the table you have to at lease have a name variable.

function myFunct(event) &nbsp; --this does something &nbsp; print(event.name,event.phase,.....) end &nbsp; local myEvent = { name = "doSomething", phase = "start", .... } myObject:addEventListener( "doSomething", myFunct ) &nbsp; function iDidSomethingThatSentMeHere() &nbsp; myObject:dispatchEvent(myEvent) end

whats happening is i hane an object that was created called myObject. when the user does whatever that causes the functin iDidSome… to run it dispatches the event i created called myEvent and myObject has an eventListener listening for an event called doSomething. so it send you to the function called myFunct and myFunct can read all the variables setup inside of myEvent. hope that helps it took me a few times playing around with it to completely grasp it

So…the way I understand it- it runs an event from within a function?

Anyways I’ll try a few things out, write some simple function and use dispatchEvent.