How to attach event listener to physic bodies?

Hi Coronaville,

In my game, player can drag objects around. Objects are Display Objects that have a physic body attached to them. To help player to grab objects more easily, I wanted to increase size that is “touchable”. So I initially tried to increase radius of my physics but I was in the dark.

Since I attach touch event listener to the Display Object, it makes complete sense that the Display Object itself is touchable (and hence draggable), not the physic attached to it.

Apparently I can’t get a handle from when I attache physic to my objects as it creates physic and adds it to the physic engine.

So how can I attach my touch event listener to the physic component attached to this Display Object, not the Display Object itself?

Thanks in advance. [import]uid: 206803 topic_id: 34594 reply_id: 334594[/import]

For each item you want to be “touchable” use a display group. First, add the image you currently have to the group and then add the physics body to the display group. Then, add another object to index 1 into the group, then add the touch listener to the group.

This way you can have physics bodies which are the same size as you are currently using, without extra work, and you can have a larger touchable area. [import]uid: 8271 topic_id: 34594 reply_id: 137541[/import]

umm, I’ve read your post several times but I just get my head around it quite well. Would you please elaborate a bit more? [import]uid: 206803 topic_id: 34594 reply_id: 137574[/import]

Ok, no problem. I’ve coded this up for you but I’m afraid that the code does not make it look easy. First, I will describe it a little:

The concept is to build a physics display group which can be easily moved using a larger touch area.

This is implemented in 5 steps:

1 - create display group
2 - add the visible display object
3 - add the physics
4 - add the larger touchable display object
5 - add a touch listener

This way, we easily create the physics body using the first display object within the group, then we add the touch listener for the larger display object.

Take a careful look at the code below - note that the two children of the ‘group’ are used for different things but that the physics body and touch object are both the ‘group’:

main.lua:
[lua]require(“physics”)
physics.start()
physics.setGravity(0,0)
physics.setDrawMode(“hybrid”)

– Please note that a lot of code here is for making things easy to see in this demo!

– Creating the group with a physics body and larger touch area for easy grabbing…

– create the group
local group = display.newGroup()
– just move the group inwards to the screen so its a bit more visible for the demo
group.x, group.y = 300, 300

– Create the physics body on the display group based on the size of the display object inside the group…

– create the physics body display object
local phys = display.newRect( group, 0, 0, 200, 50 )
– center the physics object in the group
phys.x, phys.y = 0, 0
– colour it for visibility
phys:setFillColor( 255, 0, 0 )
– add the physics object (important because we cannot add the body to the content of the group)
physics.addBody( group )

– Create an object to serve as the touch area…

– add the touchable object
local touchable = display.newRect( group, 0, 0, 300, 100 )
– not necessary because it would normally be invisible, but lets move the touch object below the physics display object
group:insert( 1, touchable )
– again, center the touchable object
touchable.x, touchable.y = 0, 0
– colour it for visibility
touchable:setFillColor( 0, 255, 0 )

– Add a standard touch listener for grabbing the body and moving it around…

– add the touch handler
function group:touch( event )
local target = event.target – get the touchable object
if (event.phase == “began”) then
display.getCurrentStage():setFocus( target ) – set the touch focus to the touchable object
target.hasFocus = true – remember we’ve set the focus
target.touchjoint = physics.newJoint( “touch”, target, event.x, event.y ) – create the joint to move the touchable object
return true
elseif (target.hasFocus) then
if (event.phase == “moved”) then
target.touchjoint:setTarget( event.x, event.y ) – move the touchable object
else
display.getCurrentStage():setFocus( nil ) – remove the touch focus
target.hasFocus = false – remember we’ve removed the focus
target.touchjoint:removeSelf() – remove the touch joint
target.touchjoint = nil
end
return true
end
return false
end
– add the touch listener to the group using the second display object as touchable area
group:addEventListener(“touch”)[/lua] [import]uid: 8271 topic_id: 34594 reply_id: 137602[/import]

For each item you want to be “touchable” use a display group. First, add the image you currently have to the group and then add the physics body to the display group. Then, add another object to index 1 into the group, then add the touch listener to the group.

This way you can have physics bodies which are the same size as you are currently using, without extra work, and you can have a larger touchable area. [import]uid: 8271 topic_id: 34594 reply_id: 137541[/import]

umm, I’ve read your post several times but I just get my head around it quite well. Would you please elaborate a bit more? [import]uid: 206803 topic_id: 34594 reply_id: 137574[/import]

Ok, no problem. I’ve coded this up for you but I’m afraid that the code does not make it look easy. First, I will describe it a little:

The concept is to build a physics display group which can be easily moved using a larger touch area.

This is implemented in 5 steps:

1 - create display group
2 - add the visible display object
3 - add the physics
4 - add the larger touchable display object
5 - add a touch listener

This way, we easily create the physics body using the first display object within the group, then we add the touch listener for the larger display object.

Take a careful look at the code below - note that the two children of the ‘group’ are used for different things but that the physics body and touch object are both the ‘group’:

main.lua:
[lua]require(“physics”)
physics.start()
physics.setGravity(0,0)
physics.setDrawMode(“hybrid”)

– Please note that a lot of code here is for making things easy to see in this demo!

– Creating the group with a physics body and larger touch area for easy grabbing…

– create the group
local group = display.newGroup()
– just move the group inwards to the screen so its a bit more visible for the demo
group.x, group.y = 300, 300

– Create the physics body on the display group based on the size of the display object inside the group…

– create the physics body display object
local phys = display.newRect( group, 0, 0, 200, 50 )
– center the physics object in the group
phys.x, phys.y = 0, 0
– colour it for visibility
phys:setFillColor( 255, 0, 0 )
– add the physics object (important because we cannot add the body to the content of the group)
physics.addBody( group )

– Create an object to serve as the touch area…

– add the touchable object
local touchable = display.newRect( group, 0, 0, 300, 100 )
– not necessary because it would normally be invisible, but lets move the touch object below the physics display object
group:insert( 1, touchable )
– again, center the touchable object
touchable.x, touchable.y = 0, 0
– colour it for visibility
touchable:setFillColor( 0, 255, 0 )

– Add a standard touch listener for grabbing the body and moving it around…

– add the touch handler
function group:touch( event )
local target = event.target – get the touchable object
if (event.phase == “began”) then
display.getCurrentStage():setFocus( target ) – set the touch focus to the touchable object
target.hasFocus = true – remember we’ve set the focus
target.touchjoint = physics.newJoint( “touch”, target, event.x, event.y ) – create the joint to move the touchable object
return true
elseif (target.hasFocus) then
if (event.phase == “moved”) then
target.touchjoint:setTarget( event.x, event.y ) – move the touchable object
else
display.getCurrentStage():setFocus( nil ) – remove the touch focus
target.hasFocus = false – remember we’ve removed the focus
target.touchjoint:removeSelf() – remove the touch joint
target.touchjoint = nil
end
return true
end
return false
end
– add the touch listener to the group using the second display object as touchable area
group:addEventListener(“touch”)[/lua] [import]uid: 8271 topic_id: 34594 reply_id: 137602[/import]