Collision detection on overlay bodies

Hello everybody - here a special problem:

Two rectangle bodies overlay each other (static) - a third rectangle (dynamic) is placed in the middle of the overlay. Now I get two collision detections - but I just want to get it from the top static rectangle. How can I manage it? Here my script:


local physics = require “physics”
physics.start()
–physics.setDrawMode( “hybrid” )
physics.setGravity( 0, 10 )

local myRectangle1 = display.newRect(150, 150, 250, 250)
myRectangle1.strokeWidth = 3
myRectangle1:setFillColor(140, 140, 140)
myRectangle1:setStrokeColor(255, 0, 0)
physics.addBody( myRectangle1, “static”)
myRectangle1.name=“red”

local myRectangle2 = display.newRect(250, 250, 250, 250)
myRectangle2.strokeWidth = 3
myRectangle2:setFillColor(140, 140, 140)
myRectangle2:setStrokeColor(0, 255, 0)
physics.addBody( myRectangle2, “static”)
myRectangle2.name=“green”

local player = display.newRect(300, 300, 50, 50)
player.strokeWidth = 3
player:setFillColor(140, 140, 140)
player:setStrokeColor(0, 0, 255)
physics.addBody( player, “dynamic”)
player.name=“player”

local function onLocalCollision( self, event )
if ( event.phase == “began”) then
print( self.name … ": collision began with " … event.other.name )
elseif ( event.phase == “ended” ) then
print( self.name … ": collision ended with " … event.other.name )
end
end

player.collision = onLocalCollision
player:addEventListener( “collision”, player )

Output:
player: collision began with green
player: collision began with red

But I just want to get the highest position - the green one - red should be ignored!
Any ideas?

Thank you
Anthony [import]uid: 125918 topic_id: 31074 reply_id: 331074[/import]

Hi Anthony,
If the red rectangle should always be ignored, you can set up collision filters so that it will never return a collision with the dynamic object. If you need more flexible control, as in, sometimes the red rectangle will be above the green one and thus need to sense collision, you might need to assign a custom z-index variable to each static object and set it depending on which is in “front”… then in the collision handler, you detect if the collision is occurring with that one and proceed if so, cancel if not.

Does this help?
Brent Sorrentino
[import]uid: 9747 topic_id: 31074 reply_id: 124335[/import]

Hi Brent,
I think I have to use the z-index to be more flexible, hope it will be easy to use :frowning:
Thank you for your help
Anthony

Here’s a another short solution - maybe usefull:

local physics = require “physics”

physics.start()
–physics.setDrawMode( “hybrid” )
physics.setGravity( 0, 10 )

local myRectangle1 = display.newRect(150, 150, 250, 250)
myRectangle1.strokeWidth = 3
myRectangle1:setFillColor(140, 140, 140)
myRectangle1:setStrokeColor(255, 0, 0)
physics.addBody( myRectangle1, “static”)
myRectangle1.name=“red”

local myRectangle2 = display.newRect(250, 250, 250, 250)
myRectangle2.strokeWidth = 3
myRectangle2:setFillColor(140, 140, 140)
myRectangle2:setStrokeColor(0, 255, 0)
physics.addBody( myRectangle2, “static”)
myRectangle2.name=“green”

local player = display.newRect(300, 300, 50, 50)
player.strokeWidth = 3
player:setFillColor(140, 140, 140)
player:setStrokeColor(0, 0, 255)
physics.addBody( player, “dynamic”)
player.name=“player”

local set = false
local function onLocalCollision( self, event )
if ( event.phase == “began” and set == false) then
set = true
print( self.name … ": collision began with " … event.other.name )
elseif ( event.phase == “ended” ) then
– print( self.name … ": collision ended with " … event.other.name )
end
return false
end

player.collision = onLocalCollision
player:addEventListener( “collision”, player )
[import]uid: 125918 topic_id: 31074 reply_id: 124497[/import]

Hi again Anthony,

I see the functionality of your short solution and how it sets a “flag” to either process the collision or not, depending on if a collision has just occurred. That might work but I don’t believe it will be reliable in the long run. Collisions of this sort happen consecutively in the same game cycle, so both might still occur in some/all instances… or perhaps not. You can test it and use the method which seems best, but certainly the z-index management method would be reliable and probably worth implementing now versus later, when it might be more complicated to do so.

Best of luck with your game!
Brent
[import]uid: 9747 topic_id: 31074 reply_id: 124571[/import]

Hi Anthony,
If the red rectangle should always be ignored, you can set up collision filters so that it will never return a collision with the dynamic object. If you need more flexible control, as in, sometimes the red rectangle will be above the green one and thus need to sense collision, you might need to assign a custom z-index variable to each static object and set it depending on which is in “front”… then in the collision handler, you detect if the collision is occurring with that one and proceed if so, cancel if not.

Does this help?
Brent Sorrentino
[import]uid: 9747 topic_id: 31074 reply_id: 124335[/import]

Hi Brent,
I think I have to use the z-index to be more flexible, hope it will be easy to use :frowning:
Thank you for your help
Anthony

Here’s a another short solution - maybe usefull:

local physics = require “physics”

physics.start()
–physics.setDrawMode( “hybrid” )
physics.setGravity( 0, 10 )

local myRectangle1 = display.newRect(150, 150, 250, 250)
myRectangle1.strokeWidth = 3
myRectangle1:setFillColor(140, 140, 140)
myRectangle1:setStrokeColor(255, 0, 0)
physics.addBody( myRectangle1, “static”)
myRectangle1.name=“red”

local myRectangle2 = display.newRect(250, 250, 250, 250)
myRectangle2.strokeWidth = 3
myRectangle2:setFillColor(140, 140, 140)
myRectangle2:setStrokeColor(0, 255, 0)
physics.addBody( myRectangle2, “static”)
myRectangle2.name=“green”

local player = display.newRect(300, 300, 50, 50)
player.strokeWidth = 3
player:setFillColor(140, 140, 140)
player:setStrokeColor(0, 0, 255)
physics.addBody( player, “dynamic”)
player.name=“player”

local set = false
local function onLocalCollision( self, event )
if ( event.phase == “began” and set == false) then
set = true
print( self.name … ": collision began with " … event.other.name )
elseif ( event.phase == “ended” ) then
– print( self.name … ": collision ended with " … event.other.name )
end
return false
end

player.collision = onLocalCollision
player:addEventListener( “collision”, player )
[import]uid: 125918 topic_id: 31074 reply_id: 124497[/import]

Hi again Anthony,

I see the functionality of your short solution and how it sets a “flag” to either process the collision or not, depending on if a collision has just occurred. That might work but I don’t believe it will be reliable in the long run. Collisions of this sort happen consecutively in the same game cycle, so both might still occur in some/all instances… or perhaps not. You can test it and use the method which seems best, but certainly the z-index management method would be reliable and probably worth implementing now versus later, when it might be more complicated to do so.

Best of luck with your game!
Brent
[import]uid: 9747 topic_id: 31074 reply_id: 124571[/import]

Also look into preCollision event.contact property [import]uid: 63787 topic_id: 31074 reply_id: 128580[/import]

Also look into preCollision event.contact property [import]uid: 63787 topic_id: 31074 reply_id: 128580[/import]