[Resolved] Global collision listener problem

Hello guys,

I am having some issue with collisions. I am using a global collision listener for all my collisions and for the most part everything works great BUT randomly the code below gets confused because “event.object1” (which I try to make it so it always refer to a planet display object) randomly sometimes refer to a “rock” display object.

The problem is that planet.health exist but rock do not have a health member (see code below) because of that I am getting an error when the code tries to access rock.health. Basically event.object1 and event.object2 do not always contains the correct objects.

I am doing all the tests before end to make sure event.object1 always contains planet objects and event.object2 rock objects. That way, i can do things to those objects depending on the type. For instance decreasing the planets health went hit with a rock object.

I am not sure if I am making any sense but i would sure appreciate some pointers and how to use global collision correctly and avoid these type of issues.

Thanks a lot.

Mo

ps: The issue mostly appears (it seems) when something is else is happening in the game (like a pressing a button or moving a joystick…) So maybe there is too much going for the collision to keep track of things…
HERE CODE (CLEANED SO TO MAKE IT EASIER TO READ)

[lua] local function onRockCollision(event)

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

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

– tests to make sure obj1 always hold reference to a “planet” object and obj2 is a “rock” object
if obj1.name == “planet” and obj2.name == “rock” then

obj1 = event.object1
obj2 = event.object2

elseif obj1 == “rock” and obj2 == “planet” then

obj1 = event.object2
obj2 = event.object1

elseif obj1.name == “gun” and obj2.name == “rock” then

obj1 = event.object1
obj2 = event.object2

elseif obj1.name == “rock” and obj2.name == “gun” then

obj1 = event.object2
obj2 = event.object1

end

if (obj1.name == “planet” and obj2.name == “rock” ) or (obj1.name == “rock” and obj2.name == “planet” ) then

– reduce planet health by some %
obj1.health = obj1.health - gameLevel*3 — THIS IS WHERE THE GAME REPORT AN ERROR (BECAUSE OBJ1 REFER TO A ROCK INSTEAD OF A PLANET DISPLAY OBJECT)

– destroy rock display object
obj2:removeSelf()
obj2=nil
return true

– check if hitting the gun cross

elseif ((obj1.name == “rock” and obj2.name == “gun”) or (obj1.name == “gun” and obj2.name == “rock”)) and gunEnable == true and stickMove == true then
– increase score code here

XXXXXXX
– destroy rock display object

obj2:removeSelf()
obj2=nil

end

return true
– end of the function
end[/lua]

[import]uid: 49236 topic_id: 24197 reply_id: 324197[/import]

Hey Mo,

With your tests in place is this still happening?

If so could you maybe use print statements to figure out which part of the code (assuming it is one specific part) is causing all the fuss?

Peach :slight_smile: [import]uid: 52491 topic_id: 24197 reply_id: 97658[/import]

Thanks Peach. I have put a print statement and that why I find out that obj1 refered to “planet” and not to rock. When that happens I get an error on the terminal and the collision do not happen (I see rock passing thru the planet) I think it happen mostly when I am doing else like pushing a button or moving an analog joystick on the screen. Even it do not happen all the time.

Thanks Peach!

Mo [import]uid: 49236 topic_id: 24197 reply_id: 97661[/import]

Is this something you know how to work around? (Sorry, I can’t quite tell from your post.) :slight_smile: [import]uid: 52491 topic_id: 24197 reply_id: 97676[/import]

Mo, Has this been resolved? I think I may or may not be having the same issue as you, but was just wondering if you got this issue resolved? [import]uid: 129334 topic_id: 24197 reply_id: 99286[/import]

I’m not sure where you are in this game, but I was running into an issue where [lua]event.object1.myName[/lua] is supposed to be “ENEMY” and [lua]event.object2.myName[/lua] is supposed to be “BULLET”. But sometimes it would get confused and obj1’s name would be “BULLET” instead of “ENEMY” and vice versa.

I think I have a workaround, but just letting you know my issue and if it was the same as yours. [import]uid: 129334 topic_id: 24197 reply_id: 99288[/import]

Hello Mark.

I am just getting back to this issue since it is almost last bug I need to deal with in my app. Yes I still have the issue. It seems random but maybe brought when a lot of things are happening (not sure about that last point). I am now going to work on this full time and would love to hear about any solution you may have.

Thanks a lot Mark.

Mo [import]uid: 49236 topic_id: 24197 reply_id: 99290[/import]

The error is in your “or” statement on line 38. Read it closely and you will notice that you are letting the rock through the test as obj1. You are letting possible permutations past in the logic above. I’ll check back with this tomorrow and maybe we can bake all that down to something much simpler… :slight_smile:
[import]uid: 21331 topic_id: 24197 reply_id: 99292[/import]

Regarding line 38, I would have written it as so:
[lua]if obj1.name == “planet” and obj2.name == “rock” then
– reduce planet health by some %
obj1.health = obj1.health - gameLevel*3
elseif obj1.name == “rock” and obj2.name == “planet” then
– reduce planet health by some %
obj2.health = obj2.health - gameLevel*3
end[/lua]

Basically, what you originally had there, said this: “hey there, whether or not obj1 or obj2 is a planet, go ahead and do something with obj1’s health.”

But in the code above, it now says: “Hey there, if obj1 is a planet, do something with obj1’s health. Otherwise, if obj2 is actually the planet, do something with obj2’s health.”

So FYI I’m a noob, so maybe I’m making stuff up =p [import]uid: 129334 topic_id: 24197 reply_id: 99295[/import]

WOW!!! What a great find guys! That makes a lot of sense and defeat all the careful tests I made ab above the if’s

Mark, I like you re-written of the code. My guess is that I do not need all the tests above the if’s then. Was that the way you fixed your issue at the time?

I still do not get why obj1 get confuse in the first place since i have tests that should have prevented for obj1 to never hold “rock”…

In any event thank you sooo much for help. I appreciated very much. I will re-code and see what I get. By the way it is really random so it is hard to test.

Thank you.

Mo. [import]uid: 49236 topic_id: 24197 reply_id: 99297[/import]

HI Mo,

Yes, that was the code I used to solve my issue. I too was not sure “why” it was getting confused from my “bullets” and “enemy”, but so far, this “workaround” “worked” for me!

I’m sure other experts have a better explanation and solution to this but for now, I’ll keep trekking along and improving, like you! [import]uid: 129334 topic_id: 24197 reply_id: 99301[/import]

Thanks Mark. I will implement the new code and report here. Thanks to you too realTonyK, I agree my logic is probably too complex for what I am trying to achieve. Any better way will be very welcome!

Mo

EDIT:

I was able to recode my “too complex” onCollision function to something like below. So far no missed collision but only time will tell since they were happening randomly for some reason. Thank you guys for pointing out the BIG error of logic in my earlier code. If you see something else please let me know but I think I am going to mark this as [SOLVED] for now:

[lua] – Global Collision function

local function onRockCollision(event)
if ( event.phase == “began” ) then
local obj1 = event.object1
local obj2 = event.object2
– check if a rock hit a planet
if obj1.name == “planet” and obj2.name == “rock” then

planetHit(obj1,obj2)

elseif obj1.name == “planet” and obj2.name == “rock” then

planetHit(obj2,obj1)

end
– check if the gun cross hit a rock

if obj1.name == “gun” and obj2.name == “rock” then

gunHit(obj1,obj2)

elseif obj1.name == “rock” and obj2.name == “gun” then

gunHit(obj2,obj1)

end

– check if the a rock hit a wall

if obj1.name == “wall” and obj2.name == “rock” then

wallHit(obj1,obj2)

elseif obj1.name == “rock” and obj2.name == “wall” then

allHit(obj2,obj1)

end

end
checkGameOver()
end[/lua] [import]uid: 49236 topic_id: 24197 reply_id: 99302[/import]

Oh man, sorry It took me too long to make it back here. Looks like Mark took good care of you. Your logic is looking much better now. You know if you used table listeners for each object you would not have to compare both objects. They would behave the way that you expected this listener to behave (event.target) would always be “the other” object. Your game will perform better with less “if-then”'s. Just a tip, and good job fixing it up! :slight_smile: [import]uid: 21331 topic_id: 24197 reply_id: 99409[/import]

No problem at all! Unfortunately I spoke too soon! (I have to remove the SOLVED sign for now) It is random but I still see rocks (asteroids) passing by planets without hitting them (collision) I am sure something is not correct in my logic still (or something else is happening)

In term of using local collision listeners, it is actual the way I started but they did seems to slow down my game for some reason. I also read in the forum that a global listener is better for performance (my game is fast action game) I may have to go back to local listener since it is much easier to deal with as you said.

My problem is that i need to do destroy a rock not the planet when a collision happens.

Back to the mines on this issue:)

Thanks again for the all help.

Mo [import]uid: 49236 topic_id: 24197 reply_id: 99414[/import]

Hello guys,

I think i may have found the issue. Stupid mistake on my part. I need to test more to see if it is true (since the problem seems to be random) but the issue was in my On-collision() function. See code below.

Not sure why the collision was not happening time to time but I will update if the issue is truly gone.

Thanks again for all the help.

Mo.

[lua]local function onRockCollision(event)

local phase = event.phase

if “began” == phase then
local obj1 = event.object1
local obj2 = event.object2
– check if a rock hit a planet
if obj1.name == “planet” and obj2.name == “rock” then

timer.performWithDelay( 1, planetHit(obj1,obj2), 1 )
–planetHit(obj1,obj2)

–elseif obj1.name == “planet” and obj2.name == “rock” then <<< PROBLEM WAS HERE. PLANET/ROCK POSITION NEED TO BE REVERSED

elseif obj1.name == “rock” and obj2.name == “planet” then

timer.performWithDelay( 1, planetHit(obj2,obj1), 1 )
–planetHit(obj2,obj1)

end[/lua] [import]uid: 49236 topic_id: 24197 reply_id: 102175[/import]

Try putting the local obj1 = event.object1 within the “IF” statements. Here’s an example:
[lua]local function onRockCollision(event)
local phase = event.phase
if “began” == phase then

–local obj1 = event.object1 --these should go within the if statements
–local obj2 = event.object2 --these should go within the if statements

– check if a rock hit a planet
if obj1.name == “planet” and obj2.name == “rock” then
local obj1 = event.object1
timer.performWithDelay( 1, planetHit(obj1,obj2), 1 )
elseif obj1.name == “rock” and obj2.name == “planet” then
local obj1 = event.object2
timer.performWithDelay( 1, planetHit(obj2,obj1), 1 )
end[/lua]

If that doesn’t work try this:

[lua]local function onRockCollision(event)
local phase = event.phase
if “began” == phase then

–local obj1 = event.object1 --these should go within the if statements
–local obj2 = event.object2 --these should go within the if statements

– check if a rock hit a planet
if obj1.name == “planet” and obj2.name == “rock” then
local obj1 = event.object2-- ONLY DIFFERENCE
timer.performWithDelay( 1, planetHit(obj1,obj2), 1 )
elseif obj1.name == “rock” and obj2.name == “planet” then
local obj1 = event.object1-- ONLY DIFFERENCE
timer.performWithDelay( 1, planetHit(obj2,obj1), 1 )
end[/lua] [import]uid: 129334 topic_id: 24197 reply_id: 102585[/import]

Hello Mark.

Thanks for your time. It seems (at least so far) that my issue has been resolved.
I think the main issue is that i was missing one condition were planet and rock are reverse on the obj1/obj2 collision. You and RealTonyK were instrumental is showing me that my logic was all wrong. I can tell you how much appreciated your guys help!

I am going to mark this issue as resolved for now.

Thanks Mark.

Mo [import]uid: 100814 topic_id: 24197 reply_id: 102589[/import]