Detect collision, but don't interact

Seems like this is a common problem, but I couldn’t find the right search terms I guess. Think of the situation in Super Mario Bros where you collect coins. I need to detect when the player touches a coin, remove the coin (and give the player points), but I don’t want the player to bounce off of the coin. He should jump through it.

The docs say this:
“preCollision”: an event type that fires right before the objects start to interact. Depending on your game logic, you may wish to detect this event and conditionally override the collision.

But there is no explanation on how to do this.

This is what I’m attempting (this is in the coin “class”):

local function preCollision( self, event )  
 obj:removeSelf();  
 obj = nil;  
 return true;  
 end  
  
 obj.preCollision = preCollision;  
 obj:addEventListener( "preCollision", obj );  

The coin always gets removed, but sometimes the player bounces off the coin. How can I make sure this doesn’t happen?

I’ve also tried putting the collision detection in the player class, but I still get erratic behavior. Is the only solution to use a global listener? [import]uid: 52127 topic_id: 9727 reply_id: 309727[/import]

I believe what you are looking for is a sensor. View it here:

http://developer.anscamobile.com/content/game-edition-physics-bodies#Sensors

Edit: I believe there is a billiards sample app you can use for reference too. [import]uid: 31262 topic_id: 9727 reply_id: 35458[/import]

Thanks for the suggestion. Unfortunately setting isSensor=true allows the player to pass through the coin, but no collision events are fired at all.

EDIT - turns out that if isSensor = true, no preCollision events are fired. You have to use the regular collision event. [import]uid: 52127 topic_id: 9727 reply_id: 35460[/import]

[lua]module(…, package.seeall)

function new()
local localGroup = display.newGroup()
local physics = require(“physics”)
physics.start()
–physics.setDrawMode( “hybrid” ) – normal, hybrid, debug

local ground = display.newRect(0,0,display.contentWidth,50)
ground.myName = “ground”
ground.y = display.contentHeight - 25
physics.addBody(ground,“static”)

local mario = display.newRect(0,0,50,80)
mario.x = 100
mario.y = 700
mario.myName = “mario”
physics.addBody(mario,“dynamic”)

local coin = {}
coin[1] = display.newCircle(0,0,20)
coin[2] = display.newCircle(0,0,20)
coin[3] = display.newCircle(0,0,20)

for i=1,#coin do
coin[i].x = mario.x + 100 * i
coin[i].y = 700
coin[i].myName = “coin”
physics.addBody(coin[i],“static”,{isSensor = true})
end

local function onCollision( event )
if ( event.phase == “began” ) then

if event.object1.myName == “mario” and event.object2.myName == “coin” then
event.object2.alpha = 0.001

end

elseif ( event.phase == “ended” ) then

if event.object1.myName == “mario” and event.object2.myName == “coin” then
event.object2:removeSelf()
event.object2 = nil
end

end
end

Runtime:addEventListener( “collision”, onCollision )
local function callMe()
mario.x = mario.x +5
end
timer.performWithDelay(50,callMe,0)

return localGroup
end[/lua]

use config file with,

application =
{
content =
{
width = 768,
height = 1024,
scale = “zoomStretch”,
antialiasing = true,
fps = 30
},

}
[import]uid: 12482 topic_id: 9727 reply_id: 35474[/import]