Can an object have two event listeners?

Thank you very much horacebury and nick_sherman! It is working exactly the way I want now. It is even working quite nicely on the s3. I love how much support the Corona community provides! [import]uid: 208811 topic_id: 36109 reply_id: 143454[/import]

No worries.

Personally, I really enjoy giving back; I’ve gotten so much support from the community myself over the years. [import]uid: 8271 topic_id: 36109 reply_id: 143455[/import]

I think I got ahead of myself when I said it worked exactly the way I want, after some testing I have realised that it is only hitting one condition in the if “moving == true” statement. I am printing out the state of the moving variable before and after I have moved a tile. This seems to be switching from false to true when a tile is moved and back to false if < 2. I have noticed that if the tile does not move at all the value returned is nil, not 0. Whatever I set local moving = false/true at the start of the function, that is state it stays with [import]uid: 208811 topic_id: 36109 reply_id: 143456[/import]

I think the ‘moving = false’ statement is in the wrong place, this should do it - tidied another possible error as well.

[lua]

local moving = false

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

local phase = event.phase

if “began” == phase then

– Make target the top-most object
local parent = t.parent
parent:insert( t )
display.getCurrentStage():setFocus( t )
t.isFocus = true

– Store initial position
t.x0 = event.x - t.x
t.y0 = event.y - t.y

elseif t.isFocus then

if “moved” == phase then

local move = math.abs(event.x - event.xStart) + math.abs(event.y - event.yStart)

if move > 2 then moving = true; end

– Make object move (we subtract t.x0,t.y0 so that moves are
– relative to initial grab point, rather than object “snapping”).
t.xScale = 1.7
t.yScale = 1.7
t.x = event.x - t.x0
t.y = event.y - t.y0

–t1 = t1…t.value
elseif “ended” == phase or “cancelled” == phase then

if moving == true then

t.x, t.y = posX[index] + (sizeX/2), posY + (sizeY/2);
index = index + 1

else

if t.container then
containers[t.container].isOccupied = false
answer[t.container] = " "
t.container = nil
–answer[t.container] = " "
end

for i = 1, #posX do
if not containers[i].isOccupied then
if (//correct condition) then
t.x, t.y = posX[i] + (sizeX/2), posY + (sizeY/2);
containers[i].isOccupied = true
t.container = i
–check to see if answer is correct
–get string from answer array
–print ( 'table: '…table.concat( answer))
s3 = table.concat(answer)
print(s3)
elseif (//another condition) then
– t.x, t.y = posX2 + (sizeX/2), posY2 + (sizeY/2);
end
end
end

t.xScale = 1
t.yScale = 1
moving = false

end

display.getCurrentStage():setFocus( nil )
t.isFocus = false

end

– Important to return true. This tells the system that the event
– should not be propagated to listeners of any objects underneath.
return true
end

[/lua] [import]uid: 93133 topic_id: 36109 reply_id: 143457[/import]

Thanks nick_sherman, I had to do a bit more work on my side to get correct answers, but it seems to but working fine now. [import]uid: 208811 topic_id: 36109 reply_id: 143468[/import]

Yes, an object can have many listeners, but it doesn’t not make sense to attach multiple listeners for the same event (I can see you’re not doing that, just wanted to highlight that.)

I think you need to work out your specific case user interaction because a began phase is not a tap. A tap (as shown by the tap event listener) is a began phase, followed by no moved phase, followed by an ended phase which is fired within a limited amount of time (about 350 milliseconds.)

Also, be aware that if you want a fairly forgiving touch listener function which handles both the touch and tap events (which is actually a wise choice) you might want to track movement made during the moved phase. The question to ask yourself is: Do you want to limit detection of a tap to literally no movement or can the touch move a little way? ie: If the moved phase is detected does that mean the event is definitely not a tap?

It might sound very pedantic, but you will rarely be able to generate a true tap event on a physical device without causing a little bit of a moved phase. This will be a bigger problem with the newer, more powerful and sensitive devices - which could explain the difference between the S2 and S3. Try ignoring a threshold amount of movement when detecting the difference between a tap and a touch. [import]uid: 8271 topic_id: 36109 reply_id: 143446[/import]

As Horacebury says, I would detect how many pixels the user has moved their finger and use this to decide what to do in the ‘ended’ phase (sorry the formatting is all over the place, I don’t have access to a code editor right now).

[lua]

local moving = false

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

local phase = event.phase

if “began” == phase then

– Make target the top-most object
local parent = t.parent
parent:insert( t )
display.getCurrentStage():setFocus( t )
t.isFocus = true

– Store initial position
t.x0 = event.x - t.x
t.y0 = event.y - t.y

elseif t.isFocus then
if “moved” == phase then

local move = math.abs(event.x - event.xStart) + math.abs(event.y - event.yStart)

if move > 2 then moving = true; end

– Make object move (we subtract t.x0,t.y0 so that moves are
– relative to initial grab point, rather than object “snapping”).
t.xScale = 1.7
t.yScale = 1.7
t.x = event.x - t.x0
t.y = event.y - t.y0

–t1 = t1…t.value
elseif “ended” == phase or “cancelled” == phase then

if moving == true then

t.x, t.y = posX[index] + (sizeX/2), posY + (sizeY/2);
index = index + 1

else

if t.container then
containers[t.container].isOccupied = false
answer[t.container] = " "
t.container = nil
–answer[t.container] = " "
end

for i = 1, #posX do
if not containers[i].isOccupied then
if (//correct condition) then
t.x, t.y = posX[i] + (sizeX/2), posY + (sizeY/2);
containers[i].isOccupied = true
t.container = i
–check to see if answer is correct
–get string from answer array
–print ( 'table: '…table.concat( answer))
s3 = table.concat(answer)
print(s3)
elseif (//another condition) then
– t.x, t.y = posX2 + (sizeX/2), posY2 + (sizeY/2);
end
end
end

t.xScale = 1
t.yScale = 1
display.getCurrentStage():setFocus( nil )
t.isFocus = false
end

moving = false
end

– Important to return true. This tells the system that the event
– should not be propagated to listeners of any objects underneath.
return true
end

[/lua] [import]uid: 93133 topic_id: 36109 reply_id: 143449[/import]

Yes, exactly. What I do is to check the distance between the began location {x=e.xStart, y=e.yStart} and the ended location {x=e.x, y=e.y} and if it is too far then report a touch, otherwise report a tap.

The only kicker with this is that if you are handling taps with a touch listener you get all the began and moved phases for a tap event, rather than a single, clean tap event.

I have tried writing listener libraries in the past which aggregate all of that but you lose the ability to fire the event and have it cascade down the display object hierarchy. [import]uid: 8271 topic_id: 36109 reply_id: 143452[/import]

Thank you very much horacebury and nick_sherman! It is working exactly the way I want now. It is even working quite nicely on the s3. I love how much support the Corona community provides! [import]uid: 208811 topic_id: 36109 reply_id: 143454[/import]

No worries.

Personally, I really enjoy giving back; I’ve gotten so much support from the community myself over the years. [import]uid: 8271 topic_id: 36109 reply_id: 143455[/import]

I think I got ahead of myself when I said it worked exactly the way I want, after some testing I have realised that it is only hitting one condition in the if “moving == true” statement. I am printing out the state of the moving variable before and after I have moved a tile. This seems to be switching from false to true when a tile is moved and back to false if < 2. I have noticed that if the tile does not move at all the value returned is nil, not 0. Whatever I set local moving = false/true at the start of the function, that is state it stays with [import]uid: 208811 topic_id: 36109 reply_id: 143456[/import]

I think the ‘moving = false’ statement is in the wrong place, this should do it - tidied another possible error as well.

[lua]

local moving = false

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

local phase = event.phase

if “began” == phase then

– Make target the top-most object
local parent = t.parent
parent:insert( t )
display.getCurrentStage():setFocus( t )
t.isFocus = true

– Store initial position
t.x0 = event.x - t.x
t.y0 = event.y - t.y

elseif t.isFocus then

if “moved” == phase then

local move = math.abs(event.x - event.xStart) + math.abs(event.y - event.yStart)

if move > 2 then moving = true; end

– Make object move (we subtract t.x0,t.y0 so that moves are
– relative to initial grab point, rather than object “snapping”).
t.xScale = 1.7
t.yScale = 1.7
t.x = event.x - t.x0
t.y = event.y - t.y0

–t1 = t1…t.value
elseif “ended” == phase or “cancelled” == phase then

if moving == true then

t.x, t.y = posX[index] + (sizeX/2), posY + (sizeY/2);
index = index + 1

else

if t.container then
containers[t.container].isOccupied = false
answer[t.container] = " "
t.container = nil
–answer[t.container] = " "
end

for i = 1, #posX do
if not containers[i].isOccupied then
if (//correct condition) then
t.x, t.y = posX[i] + (sizeX/2), posY + (sizeY/2);
containers[i].isOccupied = true
t.container = i
–check to see if answer is correct
–get string from answer array
–print ( 'table: '…table.concat( answer))
s3 = table.concat(answer)
print(s3)
elseif (//another condition) then
– t.x, t.y = posX2 + (sizeX/2), posY2 + (sizeY/2);
end
end
end

t.xScale = 1
t.yScale = 1
moving = false

end

display.getCurrentStage():setFocus( nil )
t.isFocus = false

end

– Important to return true. This tells the system that the event
– should not be propagated to listeners of any objects underneath.
return true
end

[/lua] [import]uid: 93133 topic_id: 36109 reply_id: 143457[/import]

Thanks nick_sherman, I had to do a bit more work on my side to get correct answers, but it seems to but working fine now. [import]uid: 208811 topic_id: 36109 reply_id: 143468[/import]