Collision Detection - Please HELP

I have the following objects in m app:-
1- Array of flyingObjects
2- SpaceShip Object
3- bounceObject (basically its a rocket moving on the screen)

I would like to perform variety of actions/functions based on each collision that would occur between any 2 objects as follow and would like to know how can i do that in my Runtime event listener (Runtime:addEventListener(“collision”, onCollision)

note: collision between flyingObject and BounceObject will not be counted (those are the enemies)

I have defined each object creation in a separate function as follow:-

  • displaySpaceShip()
  • dislayBounceObject()
  • displayFlayingObject()
  • displayBullet()

for each function i have added the following collision definition:-

For spaceShip:-
spaceShip.collision = onCollision
spaceShip:addEventListener( “collision”, spaceShip )

For flyingObject:-
flyingObject.collision = onCollision
flyingObject:addEventListener( “collision”, flyingObject )

For BounceObject:-
bounce.collision = onCollision
bounce:addEventListener( “collision”, bounce )

For BounceObject:-
bullet.collision = onCollision
bullet:addEventListener( “collision”, bullet )

I need to know whats wrong in the following code and if possible how it could be fixed:-
function onCollision( self,event )
print( "Collision: Self: “…self.objectName…” & Other: "…event.other.objectName)
ipointerX = event.other.x
ipointerY = event.other.y
if ( event.phase == “began” ) then
totalKilled =totalKilled + 1
nemesisObject.text = "Killed Nemesis: " … totalKilled
if ( event.other.objectName == “bullet” ) and ( self.objectName == “bounce” ) then
levelCounter[1] = levelCounter[1] + 1500
else
levelCounter[1] = levelCounter[1] + 100
end
scoreObject.text = "Score: "…levelCounter[1]
timer.performWithDelay(100, library.DisplayCounter,1)
if ( event.other.objectName == “spaceShip” ) then
event.other:play({loop=2, remove=true}) – stop spaceShip Animation
else
– remove the bullet
end
self:removeSelf() – flyingObject
if ((event.other.objectName == “spaceShip”) or (self.objectName == “spaceShip”)) then
if ( event.phase == “began” ) then
library.playBombAnimation()
remainingSouls = remainingSouls - 1
cancelTransition = true
Runtime:removeEventListener(“enterFrame”, library.shakeNemesis)
objectBackground:addEventListener(“touch”, resumeGame)
end
end
end
end
[import]uid: 11038 topic_id: 3907 reply_id: 303907[/import]

its much easier to read if you use the [blockcode] and [/blockcode] tags either sinde of your code block [import]uid: 9371 topic_id: 3907 reply_id: 11904[/import]

Sorry i didn’t get your point? what do you mean by “its much easier to read if you use the and tags either sinde of your code block”??

Thanks [import]uid: 11038 topic_id: 3907 reply_id: 11913[/import]

Use blockcode in <> and /blockcode in <>

Then it formats it like this

[blockcode]

function doDah()

collectgarbage(“collect”)
print("Number of childen : “…curstage.numChildren)
print(“System Memory : " …(collectgarbage(“count”)/1000)…” MB”)
print(“Texture Memory : “…(system.getInfo(“textureMemoryUsed”)/1000000)…” MB”)
end

[/blockcode]

It indents correctly making it easier to read.

See here - http://developer.anscamobile.com/filter/tips [import]uid: 9371 topic_id: 3907 reply_id: 11914[/import]

[blockcode]function onCollision( self,event )
print( "Collision: Self: “…self.objectName…” & Other: "…event.other.objectName)
ipointerX = event.other.x
ipointerY = event.other.y
if ( event.phase == “began” ) then
totalKilled =totalKilled + 1
nemesisObject.text = "Killed Nemesis: " … totalKilled
if ( event.other.objectName == “bullet” ) and ( self.objectName == “bounce” ) then
levelCounter[1] = levelCounter[1] + 1500
else
levelCounter[1] = levelCounter[1] + 100
end
scoreObject.text = "Score: "…levelCounter[1]
timer.performWithDelay(100, library.DisplayCounter,1)
if ( event.other.objectName == “spaceShip” ) then
event.other:play({loop=2, remove=true}) – stop spaceShip Animation
else
– remove the bullet
end
self:removeSelf() – flyingObject
if ((event.other.objectName == “spaceShip”) or (self.objectName == “spaceShip”)) then
if ( event.phase == “began” ) then
library.playBombAnimation()
remainingSouls = remainingSouls - 1
cancelTransition = true
Runtime:removeEventListener(“enterFrame”, library.shakeNemesis)
objectBackground:addEventListener(“touch”, resumeGame)
end
end
end
end
[/blockcode] [import]uid: 11038 topic_id: 3907 reply_id: 11918[/import]

That’s better, not too sure if you are indenting your code like this, but it helps, perhaps the forum has formatted it badly for you.

[blockcode]
if (soccerball.x - event.x > 0) then
if( soccerball.angularVelocity < 500) then
if (opt_difficulty == “easy”) then
soccerball:applyTorque( event.x / 10)
else
soccerball:applyTorque( event.x / 50)
end
end
xf = (soccerball.x - event.x) / 5
else
if (soccerball.angularVelocity > -500) then
if (opt_difficulty == “easy”) then
soccerball:applyTorque( -event.x / 10)
else
soccerball:applyTorque( -event.x / 50)
end
end
xf = (soccerball.x - event.x) / 5
end

[/blockcode]
[import]uid: 9371 topic_id: 3907 reply_id: 11922[/import]

Thats what i have written finally in the onCollision function which im not sure if it the correct thing to detect each collision. Please just let me know if im doing correct in detecting each collision

[blockcode]
function onCollision( self,event )
–print( "Collision: Self: “…self.objectName…” & Other: "…event.other.objectName)
ipointerX = event.other.x
ipointerY = event.other.y
if ( event.phase == “began” ) then
totalKilled =totalKilled + 1
nemesisObject.text = "Killed Nemesis: " … totalKilled
if ((self.objectName == “bounce”) and (event.other.objectName == “bullet”)) or
((self.objectName == “bullet”) and (event.other.objectName == “bounce”)) then
levelCounter[1] = levelCounter[1] + 1500
self:removeSelf() – remove Bounce
event.other:removeSelf() – remove Bullet
elseif ((self.objectName == “flyingObject” ) and ( event.other.objectName == “bullet”)) or
((self.objectName == “bullet” ) and ( event.other.objectName == “flyingObject”)) then
levelCounter[1] = levelCounter[1] + 100
self:removeSelf() – remove flyingObject
event.other:removeSelf() – remove Bullet
elseif ( (self.objectName == “flyingObject” ) and ( event.other.objectName == “spaceShip”) ) or
( (self.objectName == “spaceShip” ) and ( event.other.objectName == “flyingObject”) ) then
self:removeSelf() – remove flyingObject
levelCounter[1] = levelCounter[1] + 100
elseif ((self.objectName == “spaceShip”) and (event.other.objectName == “bounce”) ) or
((self.objectName == “bounce”) and (event.other.objectName == “spaceShip”) ) then
destroySpaceShip()
event.other:removeSelf() – remove Bounce
levelCounter[1] = levelCounter[1] + 1500
end
scoreObject.text = "Score: "…levelCounter[1]
timer.performWithDelay(100, library.DisplayCounter,1)
end
end
[/blockcode] [import]uid: 11038 topic_id: 3907 reply_id: 11925[/import]

It might be necessary to separate out the collisions so that they refer to the different objects rather than pulling all the collisions into one function.

So for instance:

Give the spaceship a listener
if it collides with bullet do x
if it collides with flying object do y

then do that for each object.
[import]uid: 10903 topic_id: 3907 reply_id: 12527[/import]

i’m not sure you need both checks. don’t both collisions fire hence you only actually need to check once?

[lua]elseif ((self.objectName == “spaceShip”) and (event.other.objectName == “bounce”) ) or
((self.objectName == “bounce”) and (event.other.objectName == “spaceShip”) ) then[/lua]

try this instead
[lua] elseif ((self.objectName == “spaceShip”) and (event.other.objectName == “bounce”) ) then[/lua]
and see if it works

also cache your event objects
[lua]local obj1 = self.objName
local obj2 = event.other.objName[/lua]

also personally i would separate out the code into single function calls for readability
[lua]local function doSpaceShipVsBounce(bounceObj)
destroySpaceShip()
bounceObj:removeSelf()
levelCounter[1] = levelCounter[1] + 1500
end

local onCollision(self, event)


elseif ((obj1 == “spaceShip”) and (obj2 == “bounce”) ) then
doSpaceShipVsBounce()


return true – stop propagation of event?[/lua]

although sometimes you might sacrifice readability for performance i guess [import]uid: 6645 topic_id: 3907 reply_id: 12552[/import]

Thanks Jmp99 you always surprise me.
I really have tried this but the problem for some reasons im unable to detect some Collisions. For intense, like im unable to detect the bullet with the upper wall image. i have used the same code used for spaceShip, bounceBody and it didn’t work.

Is there any limitation of number of body collisions ?

im using the following code to detect the bullet collision with the floor body collision in my library.lua; the onCollision function is in my main.lua. I tried tried all possible changes to the physics body specs (“dynamic”, static", …etc) :frowning:

[blockcode]
function displayFloor()

local floorObject = display.newImage(storgeFolders[“rootImages”]…“footer.png”)
physics.addBody(floorObject,“static”, {bounce = 0.1, fraction=1.0, denisty=0.0 })
floorObject.y = display.contentHeight - floorObject.stageHeight / 2
floorObject.objectName = “floorObject”
floorObject.collision = onCollision
floorObject:addEventListener( “collision”, floorObject )
localGroup:insert(floorObject) --For collision detection
end
[/blockcode]
[import]uid: 11038 topic_id: 3907 reply_id: 12613[/import]

I forget to add this jmp99.
The problem in my case that i have 4-5 sets of collisions, first bullet Vs SpaceShip, then bullet Vs. Floor, SpaceShip Vs. BounceObject, bullet Vs. BounceObject, and so on.

Im still confused about how to manage the collisions? How to determine the source and the event in my case? which one should come first :frowning:

i know im might be a stupid question but really i couldn’t get it

You always surprise me with your answers :slight_smile: [import]uid: 11038 topic_id: 3907 reply_id: 12615[/import]

like you had seems fine, i was just separating it out into functions so it’s easier to read through.

did you find out if the double check was necessary?

if (obj1==“A” and obj2==“B”) or (obj1==“B” and obj2==“A”)

i don’t think it is, but i’m not sure. I assumed that the collision fires twice (once for each object) so you’d just process the first one and tell the system the collision is handled

j. [import]uid: 6645 topic_id: 3907 reply_id: 12627[/import]

Yes, you were correct. I must double check. But my problem is still exist. How can i detect collision with a static body (i.e physics.addBody(line,“static”,“static”, {bounce = 0.1, fraction=1.0, denisty=0.0 }) ?

I need to destroy all objects touches this line. I know this could be done on the object that would touch the line by adding a collision detection with that object. But im wondering if the detection with a static object is applicable.

Thanks [import]uid: 11038 topic_id: 3907 reply_id: 12637[/import]

Collision with a static body should be the same as any other. [import]uid: 10903 topic_id: 3907 reply_id: 12641[/import]

its not. try it. display 2 static bodies and try to detect the collision, it wont work [import]uid: 11038 topic_id: 3907 reply_id: 12645[/import]

you can run the program below and see that round balls that hit the line are removed after collision. whereas square “balls” don’t do anything, as i check the type (my custom parameter “is”) in the collision event

note here I also have an enterFrame check on every ball to see if it goes outside of the screen. i wouldnt normally add an enterframe to each ball, I would actually keep a list of balls and do a single runtime enterframe that checked the list to see which balls left the screen and could be removed

but i’ve done it this way for simplicity not performance

[lua]local physics = require(“physics”)
local rnd = math.random

physics.start()

local line = display.newRect(0,300,170,20)
line:setFillColor(255,0,0)
line.is=“line”
physics.addBody(line, “static”, {density=1})

local function removeBall(obj)
Runtime:removeEventListener(“enterFrame”, obj)
obj:removeSelf()
end
local function globalCollision(event)

local obj1 = event.object1
local obj2 = event.object2

– if round ball hits line
if(obj2.is==“round” and obj1.is==“line”) then
– call our remove function
removeBall(obj2)
end

end
local function newBall()

local ball

local radius = rnd(50)+5
local pick = math.floor(rnd(2))

if(pick==1) then

ball = display.newCircle(rnd(280)+20, 20, radius)
physics.addBody(ball, “dynamic”, {density=0.5, bounce=0.5,radius=radius})
ball.is=“round”

elseif(pick==2) then

ball = display.newRect(rnd(280)+20, 20,4,4)
physics.addBody(ball, “dynamic”, {density=1, bounce=0.1})
ball.is=“square”

end

ball:setFillColor(0,255,0)
ball.isBullet=true

– to be safe remove balls if they fall off the lower part of the screen
– otherwise they will continue falling forever
ball.enterFrame=function(self, event)
local ypos = self.y
if(ypos > 300) then self:setFillColor(255,0,0) end
if(ypos > 400) then removeBall(self) end
end

Runtime:addEventListener(“enterFrame”, ball)

end

Runtime:addEventListener(“collision”, globalCollision)
timer.performWithDelay(100,newBall,-1)[/lua] [import]uid: 6645 topic_id: 3907 reply_id: 12648[/import]

Yes i know this, but if you have read my previous reply you would know exactly what i meant. I said “ts not. try it. display 2 static bodies and try to detect the collision, it wont work” as i cannot detect collision between 2 static objects. I’ve updated the code to show what i meant.
[blockcode]

local physics = require(“physics”)
local rnd = math.random

physics.start()

local line = display.newRect(0,300,170,20)
line:setFillColor(255,0,0)
line.is=“line”
physics.addBody(line, “static”, {density=1})

local function removeBall(obj)
Runtime:removeEventListener(“enterFrame”, obj)
obj:removeSelf()
end

local function globalCollision(event)

local obj1 = event.object1
local obj2 = event.object2

– if round ball hits line
if(obj2.is==“round” and obj1.is==“line”) then
– call our remove function
removeBall(obj2)
end

end

local function newBall()

local ball

local radius = rnd(50)+5
local pick = math.floor(rnd(2))

if(pick==1) then

ball = display.newCircle(rnd(280)+20, 20, radius)
physics.addBody(ball, “static”, {density=0.5, bounce=0.5,radius=radius})
ball.is=“round”
transition.to(ball, {time=700,
alpha=5.0,delay=10,transition=easing.outQuad,
alpha=1.0, y=410}) — The collision herein will not be detected and the balls will pass through the wall normally

elseif(pick==2) then

ball = display.newRect(rnd(280)+20, 20,4,4)
physics.addBody(ball, {density=1, bounce=0.1})
ball.is=“square”

end

ball:setFillColor(0,255,0)
ball.isBullet=true

– to be safe remove balls if they fall off the lower part of the screen
– otherwise they will continue falling forever
ball.enterFrame=function(self, event)
local ypos = self.y
if(ypos > 300) then self:setFillColor(255,0,0) end
if(ypos > 400) then removeBall(self) end
end

Runtime:addEventListener(“enterFrame”, ball)

end

Runtime:addEventListener(“collision”, globalCollision)
timer.performWithDelay(1000,newBall,-1)
[/blockcode]

[import]uid: 11038 topic_id: 3907 reply_id: 12653[/import]

static bodies dont collide with each other… its in the documentation

static bodies don’t move, and don’t interact with each other; examples of static objects would include the ground, or the walls of a pinball machine.

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

[import]uid: 6645 topic_id: 3907 reply_id: 12655[/import]

Thanks man.
my problem is happens after completion of the transition function as i’m using the onComplete=removeThisObject, however, during the game the bullet may collide with the spaceship’s bullet and in this case I’m detecting the collision in onCollision function to self remove both object. Therfore, the terminal shows the following error which is correct:-

[blockcode]
attempt to call method ‘removeSelf’ (a nil value)
[/blockcode]

However, this is the removeThisObject function:-
[blockcode]
function removeThisObject(obj)
–print(obj.objectName)
if (obj~= nil) then
obj:removeSelf()
end
end
[/blockcode]

As you see im checking if the object trying to remove is nil or not (already removed) before removing it, but for some reasons its not working. and this what causes the problem

BulletObject Init function:-
[blockcode]
nemesisBullet = display.newLine( nemesisX, nemesisY, nemesisX, nemesisY+8 )
nemesisBullet:setColor( 255, 255, 255, 255 )
nemesisBullet.width = 2
nemesisBullet.objectName = “nemesisBullet”
nemesisBullet.collision = bulletVsSpaceShipCollision
nemesisBullet:addEventListener( “collision”, nemesisBullet )
physics.addBody(nemesisBullet, “static”,{bounce = 0.3, fraction=1.0, denisty=0.0 })
–nemesisBullet.collision = onCollision
–nemesisBullet:addEventListener( “collision”, nemesisBullet )
nemesisGroup:insert(nemesisBullet)
transition.to(nemesisBullet, {time=xSpeedInSeconds, delay=10, alpha=1.0,
transition=easing.outQuad,y=460, onComplete=removeThisObject})
[/blockcode]

Hope i have explained my problem completely
[import]uid: 11038 topic_id: 3907 reply_id: 12659[/import]

that code works fine for me by itself… it must be something you’re doing elsewhere [import]uid: 6645 topic_id: 3907 reply_id: 12661[/import]