Collision Problem

I have an issue with my collision listener; it is failing to detect the collision at all. Can someone please tell me what is wrong and provide a solution? Thanks.

Here is the code: 

[lua]

local escapesensor = display.newImage(“PlanetCollisionSensor.png”)

escapesensor.x = display.contentWidth/2

escapesensor.y = -20

physics.addBody(escapesensor, “static”)

escapesensor.isSensor = true

escapesensor.alpha = 0.01

escapesensor.rotation = 90

local escapesensor2 = display.newImage(“PlanetCollisionSensor.png”)

escapesensor2.x = display.contentWidth/2 

escapesensor2.y = 340

physics.addBody(escapesensor2, “static”)

escapesensor2.isSensor = true

escapesensor2.alpha = 0.01

escapesensor2.rotation = 90

local function escapeSensorCollision(self,event)

if (event.phase == “began”) then

if (event.other.name == “bluespaceship” or “redspaceship” or “purplespaceship” or “greenspaceship” or “bluegreenspaceship” or “pinkpurplespaceship”) then

spaceshipLives = spaceshipLives - 1

print(“Collision Received!”)

display.remove(event.other)

event.other = nil

end

end

end

escapesensor.collision = escapeSensorCollision

escapesensor:addEventListener(“collision”, escapesensor)

escapesensor2.collision = escapeSensorCollision

escapesensor2:addEventListener(“collision”, escapesensor2)

[/lua]

Basically, I have two rectangular sensors that detect whether a spaceship has hit it or not, and they are failing to detect the collisions. 

Physics bodies that are “static” can only collide with “dynamic” physics bodies. It looks like both of your objects are static.

Also, I don’t see how you are placing force on the objects, but remember that transition. to isn’t a physical movement, and may not cause a collision.

http://docs.coronalabs.com/api/type/Body/bodyType.html

Thank you so much! I had set the spaceship type to kinematic because of some bug before, but now that I’ve fixed that bug and changed the type, it works fine. 

I have one more question. When my game ends, the error ‘attempt to index field ‘contentBounds’ (a nil value)’ appears. I know the reason why the error is happening because it’s trying to access a function that is nil at the end of the game. I just don’t know how to fix it. Could you provide a solution to me?

Here is the code where the error is happening:

[lua]

local function hasCollided( obj1, obj2 )

  if ( obj1 == nil ) then  --make sure the first object exists

return false

  end

  if ( obj2 == nil ) then  --make sure the other object exists

      return false

  end

  local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin

  local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax

   local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin

     local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax

     return (left or right) and (up or down)

end

[/lua]

It is trying to access the variables, left, right, up, and down, but I’m not sure how to prevent this from happening. Thanks so much.

Remember, if you’re calling any Runtime functions, you need to stop them when you exit the scene or end the game. If you have a “hasCollided” function running on a constant Runtime loop, remember to remove it when the game ends.

I know the function needs to be removed, but how do I remove a function? Just like removing a display object using ‘display.remove(object); object = nil;’, how do you do that for functions?

Without seeing your code, the above comment was referencing the fact that I assumed you were calling the hasCollided function as a Runtime listener. To learn more about functions, how they work and adding/removing them, check the below guide, as it will explain it better than I ever could:

http://docs.coronalabs.com/guide/events/detectEvents/index.html

My hasCollided function isn’t a Runtime listener. I just call it whenever it needs to be called, and the place where I need it to be called is in a Runtime listener. I remove that Runtime listener when the game ends, but the error still remains, so I’m not sure how to remove it. I’m sorry if I didn’t make this clear. 

Throw up some of your code so we can take a peek at where the error might lie.

I have one large Runtime listener with a few Runtime listeners in it. Since the code for the large Runtime listener is too long, I’ll just post the small Runtime listener that uses the hasCollided function.

[lua]

local function detectSwipability(event)

     local target = event.target 

     local phase = event.phase

   

        if (hasCollided(bluespaceship, quadrant5)) then

bluespaceship.swipable = true

local function glowBlueSpaceship()

local function glowAlpha()

bluespaceshipGlowing = transition.to(bluespaceship,{time=100, alpha=1, onComplete=glowBlueSpaceship})

end

bluespaceshipGlowing = transition.to(bluespaceship, {time=100, alpha=0.95, onComplete=glowAlpha})

end

bluespaceshipGlowing = transition.to(bluespaceship,{time=100, alpha=1, onComplete=glowBlueSpaceship})

elseif (hasCollided(bluespaceship, quadrant6)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

elseif(hasCollided(bluespaceship, quadrant7)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

elseif(hasCollided(bluespaceship, quadrant8)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

else

if (bluespaceship ~= nil) then

bluespaceship.swipable = false

end

end

end

Runtime:addEventListener(“enterFrame”, detectSwipability)

[/lua]

The problem with your code is that whilst you do check for obj1/obj2 being nil, you do not check for obj1.contentBounds being present. 

If it is not present the obj1.contentBounds will return nil, and when you try to index that - obj1.contentBounds.xMin it throws a wobbler because obj1.contentBounds is not a table.

You need to find in your code the reason why obj1 has been ‘cancelled’ so to speak, but the reference itself has not been nilled.

I see now! When I put in conditions checking if obj.contentBounds and obj2.contentBounds are nil, the error goes away. Thanks so much!

Physics bodies that are “static” can only collide with “dynamic” physics bodies. It looks like both of your objects are static.

Also, I don’t see how you are placing force on the objects, but remember that transition. to isn’t a physical movement, and may not cause a collision.

http://docs.coronalabs.com/api/type/Body/bodyType.html

Thank you so much! I had set the spaceship type to kinematic because of some bug before, but now that I’ve fixed that bug and changed the type, it works fine. 

I have one more question. When my game ends, the error ‘attempt to index field ‘contentBounds’ (a nil value)’ appears. I know the reason why the error is happening because it’s trying to access a function that is nil at the end of the game. I just don’t know how to fix it. Could you provide a solution to me?

Here is the code where the error is happening:

[lua]

local function hasCollided( obj1, obj2 )

  if ( obj1 == nil ) then  --make sure the first object exists

return false

  end

  if ( obj2 == nil ) then  --make sure the other object exists

      return false

  end

  local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin

  local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax

   local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin

     local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax

     return (left or right) and (up or down)

end

[/lua]

It is trying to access the variables, left, right, up, and down, but I’m not sure how to prevent this from happening. Thanks so much.

Remember, if you’re calling any Runtime functions, you need to stop them when you exit the scene or end the game. If you have a “hasCollided” function running on a constant Runtime loop, remember to remove it when the game ends.

I know the function needs to be removed, but how do I remove a function? Just like removing a display object using ‘display.remove(object); object = nil;’, how do you do that for functions?

Without seeing your code, the above comment was referencing the fact that I assumed you were calling the hasCollided function as a Runtime listener. To learn more about functions, how they work and adding/removing them, check the below guide, as it will explain it better than I ever could:

http://docs.coronalabs.com/guide/events/detectEvents/index.html

My hasCollided function isn’t a Runtime listener. I just call it whenever it needs to be called, and the place where I need it to be called is in a Runtime listener. I remove that Runtime listener when the game ends, but the error still remains, so I’m not sure how to remove it. I’m sorry if I didn’t make this clear. 

Throw up some of your code so we can take a peek at where the error might lie.

I have one large Runtime listener with a few Runtime listeners in it. Since the code for the large Runtime listener is too long, I’ll just post the small Runtime listener that uses the hasCollided function.

[lua]

local function detectSwipability(event)

     local target = event.target 

     local phase = event.phase

   

        if (hasCollided(bluespaceship, quadrant5)) then

bluespaceship.swipable = true

local function glowBlueSpaceship()

local function glowAlpha()

bluespaceshipGlowing = transition.to(bluespaceship,{time=100, alpha=1, onComplete=glowBlueSpaceship})

end

bluespaceshipGlowing = transition.to(bluespaceship, {time=100, alpha=0.95, onComplete=glowAlpha})

end

bluespaceshipGlowing = transition.to(bluespaceship,{time=100, alpha=1, onComplete=glowBlueSpaceship})

elseif (hasCollided(bluespaceship, quadrant6)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

elseif(hasCollided(bluespaceship, quadrant7)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

elseif(hasCollided(bluespaceship, quadrant8)) then

bluespaceship.swipable = false

bluespaceship.alpha = 1

else

if (bluespaceship ~= nil) then

bluespaceship.swipable = false

end

end

end

Runtime:addEventListener(“enterFrame”, detectSwipability)

[/lua]

The problem with your code is that whilst you do check for obj1/obj2 being nil, you do not check for obj1.contentBounds being present. 

If it is not present the obj1.contentBounds will return nil, and when you try to index that - obj1.contentBounds.xMin it throws a wobbler because obj1.contentBounds is not a table.

You need to find in your code the reason why obj1 has been ‘cancelled’ so to speak, but the reference itself has not been nilled.