Listening for collisions between objects created in a function?

Hi

I’m trying to learn about collisions and have hit a snag. In the example code I have an object called “bullet” which is spawned by a function on tapping the “player1.” Additionally, I have an “alien” object, spawned by a function to randomly generate it’s position off screen.

The player1 object detects collisions between the others, but crucially, the other objects don’t listen for collisions. The code causing me problems is between lines 68-75.

If I put the listeners for either object outside of their functions I get an “attempt to global bullet (a nil value)” error.

If I make the functions global it doesn’t make any difference.

I know there’s extensive documentation on the subject of Collision Detection, but I just can’t seem to find an answer to this particular problem.

physics = require("physics")  
physics.start()  
physics.setGravity(0,5)  
   
\_H = display.contentHeight;  
\_W = display.contentWidth;  
mRand = math.random;  
local player1 = display.newImage("player.png")  
player1.x = \_W / 2  
player1.y = \_H - player1.contentHeight  
--player1:setFillColor(0, 0, 255)  
physics.addBody(player1, "kinematic", {density = 1.0, friction = 1, bounce = 0.2})  
player1.myName = "player1"  
  
local function dragplayer1 (event)  
player1.x = event.x  
--player1.y = event.y  
end  
  
local function shoot (event)  
 local bullet = display.newRect(0, 0, 5, 20)   
 bullet.x = player1.x  
 bullet.y = player1.y - 20  
 bullet:setFillColor(255, 0, 0)  
 physics.addBody(bullet, "dynamic", {density = 10.0, friction = 0, bounce = 0})  
 bullet:setLinearVelocity( 0, -1000)  
 bullet.myName = "bullet"  
  
 bullet.collision = onLocalCollision  
 bullet:addEventListener( "collision", bullet )  
end  
  
player1:addEventListener ("touch", dragplayer1)  
player1:addEventListener ("tap", shoot)  
  
local function spawnAlien()  
 local alien = display.newRect(0, 0, 60, 60)  
 alien.x = mRand(0, \_W)  
 alien.y = \_H / \_H - 50  
 alien:setFillColor(255, 0, 0)  
 physics.addBody(alien, {density = 1.0, friction = 1, bounce = 0.2})  
 alien.myName = "alien"  
  
 alien.collision = onLocalCollision  
 alien:addEventListener( "collision", alien )  
end  
  
local ground = display.newRect(0, 0, \_W, 5)  
ground.x = \_W / 2  
ground.y = \_H - 5  
ground:setFillColor(0, 255, 0)  
physics.addBody(ground, "static", {density = 1.0, friction = 1, bounce = 0.2})  
ground.myName = "ground"  
local function onLocalCollision( self, event )  
 if ( event.phase == "began" ) then  
 if (self.myName == "player1" and event.other.myName == "alien") then  
 print("yipee")  
 local function deleteSelf()  
 player1:removeSelf()  
 end  
 Timer1 = timer.performWithDelay(1,deleteSelf, 1)   
 end  
  
 if (self.myName == "bullet" and event.other.myName == "alien") then  
 print("ZAP!")  
 local function deleteBoth()  
 bullet:removeSelf()  
 alien:removeSelf()  
 end  
 Timer1 = timer.performWithDelay(1,deleteBoth, 1)   
 end  
   
 print( self.myName .. ": collision began with " .. event.other.myName )   
   
 end  
end  
  
player1.collision = onLocalCollision  
player1:addEventListener( "collision", player1 )  
  
Timer1 = timer.performWithDelay(2000,spawnAlien, 0)   

Thanks [import]uid: 67933 topic_id: 13659 reply_id: 313659[/import]

actually i can’t got your question but it seems by looking at this

local function deleteBoth()
bullet:removeSelf()
alien:removeSelf()
end
Timer1 = timer.performWithDelay(1,deleteBoth, 1)
you want to delete both object on collition
actually you can’t do this in began phase as both objects are in use internally at this time so i suggest make bullet issensor true and on began set alpha to 0 and at the ended phase delete both object

i think i had given right answer [import]uid: 12482 topic_id: 13659 reply_id: 50138[/import]

oops i am wrong can you try with Runtime listener for collition [import]uid: 12482 topic_id: 13659 reply_id: 50139[/import]

here’s the solution

[lua]physics = require(“physics”)
physics.start()
physics.setGravity(0,5)

_H = display.contentHeight;
_W = display.contentWidth;
mRand = math.random;

local player1 = display.newCircle(0,0,30)
player1.x = _W / 2
player1.y = _H - player1.contentHeight
physics.addBody(player1, “kinematic”, {density = 1.0, friction = 1, bounce = 0.2})
player1.myName = “player1”

local function dragplayer1 (event)
player1.x = event.x
end

local function shoot (event)
local bullet = display.newRect(0, 0, 5, 20)
bullet.x = player1.x
bullet.y = player1.y - 20
bullet:setFillColor(255, 0, 0)
physics.addBody(bullet, “dynamic”, {density = 10.0, friction = 0, bounce = 0})
bullet:setLinearVelocity( 0, -1000)
bullet.myName = “bullet”

end

player1:addEventListener (“touch”, dragplayer1)
player1:addEventListener (“tap”, shoot)

local function spawnAlien()
local alien = display.newRect(0, 0, 60, 60)
alien.x = mRand(0, _W)
alien.y = _H / _H - 50
alien:setFillColor(255, 0, 0)
physics.addBody(alien, {density = 1.0, friction = 1, bounce = 0.2})
alien.myName = “alien”

end

local ground = display.newRect(0, 0, _W, 5)
ground.x = _W / 2
ground.y = _H - 5
ground:setFillColor(0, 255, 0)
physics.addBody(ground, “static”, {density = 1.0, friction = 1, bounce = 0.2})
ground.myName = “ground”

function onLocalCollision( event )
if ( event.phase == “ended” ) then
print(event.object1.myName)
print(event.object2.myName)
if(event.object1.myName == “player1” and event.object2.myName == “alien”) then
print(“yipee”)
player1:removeSelf()

end

if (event.object1.myName == “alien” and event.object2.myName == “bullet”) or (event.object1.myName == “bullet” and event.object2.myName == “alien”) then
print(“called”)
event.object1:removeSelf()
event.object1 = nil
event.object2:removeSelf()
event.object2 = nil
end

end
end

Runtime:addEventListener( “collision”, onLocalCollision )

Timer1 = timer.performWithDelay(2000,spawnAlien, 0) [/lua] [import]uid: 12482 topic_id: 13659 reply_id: 50140[/import]

Fantastic,

thanks for your help.

still not sure why I couldn’t get the bullet and alien objects to listen locally for collisions though, any ideas?

[import]uid: 67933 topic_id: 13659 reply_id: 50155[/import]

that code is also fine see

[lua]physics = require(“physics”)
physics.start()
physics.setGravity(0,5)

_H = display.contentHeight;
_W = display.contentWidth;
mRand = math.random;

local player1 = display.newCircle(0,0,30)
player1.x = _W / 2
player1.y = _H - player1.contentHeight
–player1:setFillColor(0, 0, 255)
physics.addBody(player1, “kinematic”, {density = 1.0, friction = 1, bounce = 0.2})
player1.myName = “player1”

local function dragplayer1 (event)
player1.x = event.x
–player1.y = event.y
end

local function shoot (event)
local bullet = display.newRect(0, 0, 5, 20)
bullet.x = player1.x
bullet.y = player1.y - 20
bullet:setFillColor(255, 0, 0)
physics.addBody(bullet, “dynamic”, {density = 10.0, friction = 0, bounce = 0})
bullet:setLinearVelocity( 0, -1000)
bullet.myName = “bullet”

bullet.collision = onLocalCollision
bullet:addEventListener( “collision”, bullet )
end

player1:addEventListener (“touch”, dragplayer1)
player1:addEventListener (“tap”, shoot)

local function spawnAlien()
local alien = display.newRect(0, 0, 60, 60)
alien.x = mRand(0, _W)
alien.y = _H / _H - 50
alien:setFillColor(255, 0, 0)
physics.addBody(alien, {density = 1.0, friction = 1, bounce = 0.2})
alien.myName = “alien”

alien.collision = onLocalCollision
alien:addEventListener( “collision”, alien )
end

local ground = display.newRect(0, 0, _W, 5)
ground.x = _W / 2
ground.y = _H - 5
ground:setFillColor(0, 255, 0)
physics.addBody(ground, “static”, {density = 1.0, friction = 1, bounce = 0.2})
ground.myName = “ground”

function onLocalCollision( self, event )
if ( event.phase == “began” ) then
if (self.myName == “player1” and event.other.myName == “alien”) then
print(“yipee”)
local function deleteSelf()
player1:removeSelf()
end
Timer1 = timer.performWithDelay(1,deleteSelf, 1)
end

if (self.myName == “bullet” and event.other.myName == “alien”) then
print(“ZAP!”)
local function deleteBoth()
display.remove(self)
display.remove(event.other)
end
Timer1 = timer.performWithDelay(1,deleteBoth, 1)
end

print( self.myName … ": collision began with " … event.other.myName )

end
end

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

Timer1 = timer.performWithDelay(2000,spawnAlien, 0) [/lua]

i was quite sure about we can’t delete object in began phase i had also found lots of problem but it is currently working what to do may be my scenario was different i can’t remember that situation
lol [import]uid: 12482 topic_id: 13659 reply_id: 50158[/import]

Excellent,

I see where I went wrong.

Thanks very much for your help!

Dan [import]uid: 67933 topic_id: 13659 reply_id: 50282[/import]