How to remove an item(Coins) when collide with an object(player)?

 started learning and developing games using Corona SDK recently and right now I am facing an issue to collect coins in the gameplay. When the player object collides with the coin object the coin should be removed/disappeared. I tried the below code which is not successful whenever the coin collides with the player it throws an error

Attempt to call method ‘translate’ (a nil value)

Below is the code I used,

------Create Coins------

function coin()
token = display.newImage(sceneContainer, “gold.png”)
token.x = math.random(320, 720)
token.y = math.random(160, 260)
token.myName = “token”
physics.addBody( token, “dynamic”, { bounce=0, friction=1, radius=20 })

local function muovi()
token:translate(-2, 0)
end

Runtime:addEventListener( “enterFrame”, muovi )
end

tmr = timer.performWithDelay(5000, coin, 0)

------Collision Function------

function onCollision( event )
if ( event.phase == “began” ) then
if event.object1.myName == “player” and event.object2.myName == “token” then
event.object2:removeSelf()
print(“hitting 1”)
elseif event.object1.myName == “token” and event.object2.myName == “player” then
event.object1:removeSelf()
print(“hitting 1”)
end
end
end
Runtime:addEventListener( “collision”, onCollision)

First of all format your code. It is hard to read it.

Try

local function coin() -- token is local variable now  local token  = display.newImage( sceneGroup, "gold.png" )  token.x      = math.random( 320, 720 ) token.y      = math.random( 160, 260 ) --token.myName = "token" -- Add body physics.addBody( token, "static", { bounce=0, friction=1, radius=20 } ) -- Add timer function token:timer() self:translate( -2, 0 ) end -- Collision function token:collision( event ) local phase, other = event.phase, event.other if phase == "began" and other.myName == "player" then display.remove( self ) end end -- Clean up function token:finalize() timer.cancel( self.mtimer ) end -- Set timer token.mtimer = timer.performWithDelay( 50, token, 0 ) -- Add our collision listener token:addEventListener( "collision" ) -- Add a finalize listener token:addEventListener( "finalize" ) return token end

@ldurniat

I tried your code, now it throws 

Attempt to index local ‘token’ (a nil value) on the line 

– > token.x      = math.random( 320, 720 )

FYI, I also added the below line after the end of the function coin()

Runtime:addEventListener( “enterFrame”, coin )

Hi @ldurniat 

I little bit modified your code and it worked thank you so much. I also wanted you to review the code once. Thanks once again. 

[lua] 

function coin()

 token = display.newImage(sceneContainer, “gold.png”)

 token.x = math.random(320, 720)

 token.y = math.random(160, 260)

 token.myName = “token”

 physics.addBody( token, “dynamic”, { bounce=0, friction=1, radius=20 })

function token:timer() self:translate( -3, 0 ) end

  token.mtimer = timer.performWithDelay( 50, token, 0 )

  function token:finalize() timer.cancel( self.mtimer ) end

   token:addEventListener( “finalize” )

function token:collision( event )

        local phase, other = event.phase, event.other

        if phase == “began” and other.myName == “player” then

            display.remove( self )

        end

     end

  token:addEventListener( “collision” )

end

tmr = timer.performWithDelay(5000, coin, 0)

[/lua]

If you blindly copied and pasted the code, then your issue is probably that you didn’t replace ‘sceneGroup’ that Idurniat used with the ‘sceneContainer’ that you were using. 

Therefore, the group you are trying to insert token into doesn’t exist, so it doesn’t create the token object. If token doesn’t exist, then token.x doesn’t exist either. 

Why are you adding the ‘enterFrame’ listener? This will create a new coin every frame and your game will quickly slow to a crawl.

With reference to your amended code, Idurniat made his changes for a reason. Making things global might make it work, but is just storing up a whole heap of trouble for later. 

https://forums.coronalabs.com/topic/72552-dear-newbie-start-slow/

Hi nick_sherman
 

You are absolutely right, I missed the sceneGroup thing. Thanks for that. I added it now. But for ‘enterFrame’ listener; if I don’t add that then the coin is not entering the screen. I am getting that I have to call the coin() function somewhere but not sure where to. Im not sure how noobie I am and I apologize if I asked you silly things. Please advise. Thanks. 

Thanks  nick_sherman,  and ldurniat

Now, I got to know how to do things. Finally, I added a timer to generate coins every 5 seconds. Started things. Let me learn slowly and develop things. 

Well, when you write a function, that code is only executed when the function is called. This can happen in a few ways:

[lua]

local doThisThing = function ()

end

doThisThing()   – run this function now, once

timer.performWithDelay(500, doThisThing)   – run this function after 500ms, once

timer.performWithDelay(250, doThisThing, 10) – run this function every 250ms, 10 times

timer.performWithDelay(1000, doThisThing, -1)  – run every 1000ms, forever or until cancelled

Runtime:addEventListener(“enterFrame”, doThisThing)  – run every frame, forever or until cancelled

[/lua]

So while adding an enterFrame will make your coin(s) appear, I suspect it’s not the behaviour you want. It’s kind of like if you need to get into the kitchen but the door is locked, one solution is to knock the door down with a sledgehammer. It’ll get you into the kitchen, but it’s probably not the right solution as it causes more problems than it solves…

The key is to read the API and study working code in all the tutorials and examples that are available. Then you’ll know what is possible and how it’s achieved, and discover that the best way to open a locked door is to find the key! :slight_smile:

Thanks again Nick for the clean explanation. I’m crystal clear now. 

I used the below

tmr = timer.performWithDelay(1000, coin, 20)

First of all format your code. It is hard to read it.

Try

local function coin() -- token is local variable now  local token  = display.newImage( sceneGroup, "gold.png" )  token.x      = math.random( 320, 720 ) token.y      = math.random( 160, 260 ) --token.myName = "token" -- Add body physics.addBody( token, "static", { bounce=0, friction=1, radius=20 } ) -- Add timer function token:timer() self:translate( -2, 0 ) end -- Collision function token:collision( event ) local phase, other = event.phase, event.other if phase == "began" and other.myName == "player" then display.remove( self ) end end -- Clean up function token:finalize() timer.cancel( self.mtimer ) end -- Set timer token.mtimer = timer.performWithDelay( 50, token, 0 ) -- Add our collision listener token:addEventListener( "collision" ) -- Add a finalize listener token:addEventListener( "finalize" ) return token end

@ldurniat

I tried your code, now it throws 

Attempt to index local ‘token’ (a nil value) on the line 

– > token.x      = math.random( 320, 720 )

FYI, I also added the below line after the end of the function coin()

Runtime:addEventListener( “enterFrame”, coin )

Hi @ldurniat 

I little bit modified your code and it worked thank you so much. I also wanted you to review the code once. Thanks once again. 

[lua] 

function coin()

 token = display.newImage(sceneContainer, “gold.png”)

 token.x = math.random(320, 720)

 token.y = math.random(160, 260)

 token.myName = “token”

 physics.addBody( token, “dynamic”, { bounce=0, friction=1, radius=20 })

function token:timer() self:translate( -3, 0 ) end

  token.mtimer = timer.performWithDelay( 50, token, 0 )

  function token:finalize() timer.cancel( self.mtimer ) end

   token:addEventListener( “finalize” )

function token:collision( event )

        local phase, other = event.phase, event.other

        if phase == “began” and other.myName == “player” then

            display.remove( self )

        end

     end

  token:addEventListener( “collision” )

end

tmr = timer.performWithDelay(5000, coin, 0)

[/lua]

If you blindly copied and pasted the code, then your issue is probably that you didn’t replace ‘sceneGroup’ that Idurniat used with the ‘sceneContainer’ that you were using. 

Therefore, the group you are trying to insert token into doesn’t exist, so it doesn’t create the token object. If token doesn’t exist, then token.x doesn’t exist either. 

Why are you adding the ‘enterFrame’ listener? This will create a new coin every frame and your game will quickly slow to a crawl.

With reference to your amended code, Idurniat made his changes for a reason. Making things global might make it work, but is just storing up a whole heap of trouble for later. 

https://forums.coronalabs.com/topic/72552-dear-newbie-start-slow/

Hi nick_sherman
 

You are absolutely right, I missed the sceneGroup thing. Thanks for that. I added it now. But for ‘enterFrame’ listener; if I don’t add that then the coin is not entering the screen. I am getting that I have to call the coin() function somewhere but not sure where to. Im not sure how noobie I am and I apologize if I asked you silly things. Please advise. Thanks. 

Thanks  nick_sherman,  and ldurniat

Now, I got to know how to do things. Finally, I added a timer to generate coins every 5 seconds. Started things. Let me learn slowly and develop things. 

Well, when you write a function, that code is only executed when the function is called. This can happen in a few ways:

[lua]

local doThisThing = function ()

end

doThisThing()   – run this function now, once

timer.performWithDelay(500, doThisThing)   – run this function after 500ms, once

timer.performWithDelay(250, doThisThing, 10) – run this function every 250ms, 10 times

timer.performWithDelay(1000, doThisThing, -1)  – run every 1000ms, forever or until cancelled

Runtime:addEventListener(“enterFrame”, doThisThing)  – run every frame, forever or until cancelled

[/lua]

So while adding an enterFrame will make your coin(s) appear, I suspect it’s not the behaviour you want. It’s kind of like if you need to get into the kitchen but the door is locked, one solution is to knock the door down with a sledgehammer. It’ll get you into the kitchen, but it’s probably not the right solution as it causes more problems than it solves…

The key is to read the API and study working code in all the tutorials and examples that are available. Then you’ll know what is possible and how it’s achieved, and discover that the best way to open a locked door is to find the key! :slight_smile:

Thanks again Nick for the clean explanation. I’m crystal clear now. 

I used the below

tmr = timer.performWithDelay(1000, coin, 20)