Using one function for touch event with many objects

I apologize if there is already a good post on this and I’ve missed it.

I’ve been studying code and haven’t found a good tutorial on how to use a single function to handle touch events for multiple objects.

My example scenario is a function to move a rect around the screen with your finger. When it overlaps another rect that has the touch event associated with the same function, the function responds to it causing the began event to fire on the underlying rect. I’ve seen forum post about using return true, but nothing in the docs (at least that I have found about that) and I have seen in examples where people set the isFocus() attribute, but I haven’t found a good explanation on how the recommended way to do this is, and how it works.

Any help would be greatly appreciated understanding this.

Thanks

Pep [import]uid: 23182 topic_id: 9801 reply_id: 309801[/import]

@pepperfleming

this is a very common thing that many developers tend to overlook, it can be easily fixed.

I do not know what your code looks like but I assume that it looks like this

[lua]if event.phase==“moved” then
–Move the rectangle in the event.target
end[/lua]

since you are using the same function for more than one rectangle.

Just use

[lua]if “began” == event.phase then
event.target.isMoving = true
–do whatever you need to make the rects moveable
elseif event.target.isMoving==true then
if “moved” == event.phase then
–Do whatever you are doing to move the rects
elseif “ended” == event.phase then
event.target.isMoving = false
end
end[/lua]

Hope that resolves your issue,

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 9801 reply_id: 35713[/import]

Thanks Jay for the reply,

a couple questions.

I’ve got 2 rects (a and b) and both have a handler for the rouch event that call a function called Touched.

so when rect A get’s touched in your code you assign the custom param isMoving to true, and continue on. But if I move the rect (currently in the “moved” phase) over rect B, it’s began phase will get fired and it’s isMoving property will also get set to true as well. This seems to result in odd behavior when they pass over each other. A will jump or B disappears.

There’s a more complicated example in the Drag Me example what uses isFocus, but again I’m not really fully getting how that all works yet.

I’ve tried doing a check in the function like setting a global variable called activeObject and in the handler setting an id of the object in the “began” phase and setting it to null in the ended, then doing a check in the function to reject objects that aren’t the active one, but it feels flaky.

I think the return true does something important, but I haven’t found much explanation in the docs about the return true behavior on event handlers.

Anyway if I’m being dense and just not getting it I apologize, any coaching in the right direction of understanding would be very appreciated.
[import]uid: 23182 topic_id: 9801 reply_id: 35717[/import]

@pepperfleming
that is where the setFocus comes into play.

think of setFocus as a way of telling the system that I am only interested in this object, so in the touches that are returned, the event.target will always be the object you specified to setFocus on. So other rects shall not get any touches

in the if “began”==event.phase then
use

display.currentStage:setFocus(event.target)

in the elseif “ended” == event.phase then
use

display.currentStage:setFocus(nil)

if you do not set the focus to nil, then all touches will still be relevant to the object and nothing else will work.

hope that helps,

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 9801 reply_id: 35719[/import]

I haven’t found much explanation in the docs about the return true behavior on event handlers.

Simple. Imagine you have a pile of 3 papers on your table.
Now imagine you take a pen and start writing on the top paper: you will see the word you wrote on all three papers (if the papers are thin enough). That’s what happen when you don’t “return true”.

“returning true” equals saying you don’t want the event to propagate. In my analogy, it means putting something (wood/metal/whatever) between the first paper and the others so the ink stops at the first paper and never reaches the others.

It is useful in many situations and it also improves the performance of your game because the engine doesn’t have to waste time calling other event listeners. [import]uid: 51516 topic_id: 9801 reply_id: 35718[/import]

Thanks Seth of the very good analogy. I appreciate the clarity.

Pep [import]uid: 23182 topic_id: 9801 reply_id: 35721[/import]

I really appreciate it, you have helped tremendously.

Pep [import]uid: 23182 topic_id: 9801 reply_id: 35722[/import]

@pepperfleming,
if you have done any development in an Object Oriented environment, you will realise that there is something called Bubbling. Rather than use an analogy, it is a simple thing, when a touch occurs, the system passes it to the object and asks, Will you handle it? now if the object handles it, it must then tell the system that this event has been handled, otherwise the system sends it to the parent which ultimately handles it.

another analogy is if kids go and spend, and cannot pay, parents have to go bail them out. If the kids have paid, they need to let the parent know that they have paid, so that the parent does not pay again.

cheers,

?:slight_smile: [import]uid: 3826 topic_id: 9801 reply_id: 35723[/import]

Will you handle it? now if the object handles it, it must then tell the system that this event has been handled
You can handle an event AND let others handle it too because they may need to. I think my analogy is simple enough and yet complete :slight_smile: [import]uid: 51516 topic_id: 9801 reply_id: 35724[/import]

Thanks everyone for clearing this up. Here’s what I’ve ended with, would you guys review for correctness and efficiency?

local function onTouch( event )
local t = event.target

if event.phase == “began” then
display.getCurrentStage():setFocus( t )
t.IsMoving = true
elseif t.IsMoving == true then
if event.phase == “moved” then
t.x = event.x
t.y = event.y
elseif event.phase == “ended” or event.phase == “cancelled” then
display.getCurrentStage():setFocus( nil )
t.IsMoving = false
end
end

return true
end

[import]uid: 23182 topic_id: 9801 reply_id: 35734[/import]