Global collision problem

Hello, I am new and I have a problem with understanding collision in Corona, I am sorry my English is not so good.

In the game, I have a player who throws fireballs at skeletons, if any fireballs hit any skeleton, I would like to remove that skeleton, but when fireball hits him, it stuck in “skeleton’s body”. Collision is not detected, and there is no warning message.

I have two groups inserted into sceneGroup.

sceneGroup:insert(fireballs);

sceneGroup:insert(runningSkeletons);

This is how I create fireballs on touch event:

fireball = display.newImageRect(“images/fireball.png”, 32, 32);

fireball.x = player.x + 20;

fireball.y = player.y;

physics.addBody( fireball, ‘dynamic’,{bounce= 0});

fireball.gravityScale = 0

fireball.type = “fire”

fireballs:insert(fireball) – insert into group

I use timer function to create new skeleton, it’s a spritesheet:

runningSkeleton = display.newSprite( runningSkeletonSheet, runningSkeletonSequenceData )

runningSkeleton.x = display.contentWidth + 200;

runningSkeleton.y = 200;

runningSkeleton:setSequence(“running”)

runningSkeleton:play();

runningSkeleton.type = “skeleton”;

physics.addBody(runningSkeleton, “dynamic”, {bounce=0});

runningSkeletons:insert(runningSkeleton)

I move these objects in enterFrame function:

for i = 1, runningSkeletons.numChildren, 1 do

runningSkeletons[i].x = runningSkeletons[i].x - speed;

end

for i = 1, fireballs.numChildren, 1 do

fireballs[i].x = fireballs[i].x + 8;

– I have also tried to setLinearVelocity instead, it did not help

end

Global collision function:

local function globalCollision(event)

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

    if (event.object1.type == “fire”

    and event.object2.type == “skeleton”) then

    print (“collision”) – not showing

    event.object2:removeSelf();

    

   – I have tried to change alpha instead of removing object, does not work

    event.object2.alpha = .5;

    end

    end

end

Runtime:addEventListener( “collision”, globalCollision );

Actually, it sometimes remove the skeleton and I can see “collision” in output, but let’s say it works one time, than next five times collision is not detected.

What am I doing wrong?

  1. Please format your future code posts.

formatyourcode.jpg

  1. Make the fireball a sensor and see how that works for you:

    fireball.isSensor = true

That should fix the ‘sticking’ issue.

Also, don’t use a runtime collision detection listener.  Use a table listener.

Something like this (may not be exactly what you want and may have typos):

local function collision( self, event ) if( event.phase == "began" and (event.other.type == "skeleton" ) ) then self:removeEventListener("collision") timer.performWithDelay( 1, function() display.remove( self ) end ) end return false end ... Then later when you make the fireball fireball.collision = collision fireball:addEventListener("collision")

Ok, that works fine. Just one more question, do you know why it does not work when using “global collision”, if I add “fireball.isSensor = true”, fireballs go through a skeleton but it does not remove fireball or skeleton? I am asking this because I am trying to understand what is happening.

Thank you

Hi @clarusgames,

I know why this is happening (in your “global” setup). Basically, as mentioned in the little alert note box here, there’s no way to tell which is the “first” and “second” object in a global collision. What I mean is, when two objects collide, one of them is event.object1 while the other one is event.object2. However, you can’t know if the event.object1/event.object2 relationship is “skeleton”/“fireball” or “fireball”/“skeleton”. That’s why your collision processes correctly sometimes but not always.

The solution is typically to detect both possibilities in your collision detection code. In your case, I’d suggest adding another “elseif” clause after your initial “if” clause, like this:

[lua]

elseif ( event.object1.type == “skeleton” and event.object2.type == “fire” ) then

   event.object1:removeSelf();

[/lua]

Hope this helps,

Brent

  1. Please format your future code posts.

formatyourcode.jpg

  1. Make the fireball a sensor and see how that works for you:

    fireball.isSensor = true

That should fix the ‘sticking’ issue.

Also, don’t use a runtime collision detection listener.  Use a table listener.

Something like this (may not be exactly what you want and may have typos):

local function collision( self, event ) if( event.phase == "began" and (event.other.type == "skeleton" ) ) then self:removeEventListener("collision") timer.performWithDelay( 1, function() display.remove( self ) end ) end return false end ... Then later when you make the fireball fireball.collision = collision fireball:addEventListener("collision")

Ok, that works fine. Just one more question, do you know why it does not work when using “global collision”, if I add “fireball.isSensor = true”, fireballs go through a skeleton but it does not remove fireball or skeleton? I am asking this because I am trying to understand what is happening.

Thank you

Hi @clarusgames,

I know why this is happening (in your “global” setup). Basically, as mentioned in the little alert note box here, there’s no way to tell which is the “first” and “second” object in a global collision. What I mean is, when two objects collide, one of them is event.object1 while the other one is event.object2. However, you can’t know if the event.object1/event.object2 relationship is “skeleton”/“fireball” or “fireball”/“skeleton”. That’s why your collision processes correctly sometimes but not always.

The solution is typically to detect both possibilities in your collision detection code. In your case, I’d suggest adding another “elseif” clause after your initial “if” clause, like this:

[lua]

elseif ( event.object1.type == “skeleton” and event.object2.type == “fire” ) then

   event.object1:removeSelf();

[/lua]

Hope this helps,

Brent