Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Collision events order
Started by rune7 Feb 02 2019 09:25 AM

9 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

rune7

[GLOBAL: userInfoPane.html]
rune7
  • Contributor

  • 353 posts
  • Corona SDK

Hi,

 

I was under the impression that preCollision is dispatched before collision event so that I can potentially alter or even disable the contact entirely. However, when testing I get collision began event and only then I get the preCollision event. Is that the intended behavior or is it a bug? 

 



[TOPIC: post.html]
#2

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Corona Geek

  • 3,039 posts
  • Corona SDK

I forget what I learned on the specific details about this years ago, but I don't think you should use these event types together. I seem to remember a response to a similar post saying that the dispatch order is not guaranteed because the purpose is distinct. You'll notice that pre/post-collision events are noisy (generate a lot of events) whereas collision began/ended only fire once per conceptual collision. This implies that, in answer to your question, you could well be getting precollision events before and after your collision began event.

 

I could easily be wrong. The above is just my train of logic.



[TOPIC: post.html]
#3

rune7

[GLOBAL: userInfoPane.html]
rune7
  • Contributor

  • 353 posts
  • Corona SDK

Hi horacebury,

 

I'm aware that these two events behave differently, but one of the purposes of the pre-collision event is to disable collision, which means that it must be sent prior to the collision event. Actually, this is the only purpose mentioned in the examples and in the documentation, so I would expect it to work flawlessly. It doesn't matter that the pre-collision is sent many times as long as at least once its sent before each collision event can be sent so I can disable it if needed.

I was also thinking to use only pre-collision and post-collision whose order should be deterministic but I'm not sure if post is not being sent too late and it will introduce a lot of additional unnecessary noise to the system.

 

I'm trying to use these events to discern when to set a fireball for example to explode when in contact with walls that have several one way physical bodies. It must be deterministic or the game will look ridiculous.

 

If this is not the proper way to disable collision under certain circumstances, does anyone knows what is?



[TOPIC: post.html]
#4

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,297 posts
  • Enterprise

it helps to know the "origin" of these events, and use Box2D's language... forget about the "pre" and "post" and their implied ordering based on Corona's names...

 

in Box2D's native terminology, Corona's "collision" event corresponds to the contact listener;  Corona's preCollision and postCollision events correspond to Box2D's pre- and post-solve listeners.

 

contact (Corona's "collision" event) should always occur before the response solving ("pre/postCollision" events).  in other words, you have to first have a contact before there's even the POSSIBILITY of needing to resolve the contact.

 

In Corona, you can use preCollision to disable the contact, effectively saying "don't resolve it".  but it does NOT happen "pre" (before) the "collision" event (which is actually the "contact" event).

 

roughly:

Box2D:   begincontact -> presolve -> postsolve -> endcontact

Corona:  collision.began -> preCollision -> postCollision -> collision.ended

 

clear as mud? :D


  • horacebury likes this

[TOPIC: post.html]
#5

rune7

[GLOBAL: userInfoPane.html]
rune7
  • Contributor

  • 353 posts
  • Corona SDK

@davebollinger,

 

Lovely explanation! That certainly clears it for me. I think it should be added to the physics tutorial and doc page for the benefit of others. That platform game example showing blocking only from one side took me completely in the wrong direction...

 

Well, the question remains how to properly filter out certain contacts. 

The situation I have is as follows:

I have a somewhat top-down rouge type of game in the making.

Some of the walls have upper and lower physics bodies. The upper one stops objects when they arrive from below and the lower ones stops objects from passing when they arrive from above. 

 

I want to resolve objects movements and for some destroy upon impact with the wall (think fireball). obviously begincontact is too early. Should I resolve instead on the postsolve despite it being noisy? I need to look into some box2d examples showing what are the intended usages for each event.



[TOPIC: post.html]
#6

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,490 posts
  • Corona SDK

I just tested pre-collision and it is working as it should.

 

Please download this: https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2015/08/oneWayPlatform.zip

 

Run it.  Tap screen.

 

If it does this, it is working: 

 

 

(Example uses SSK for my convenience, but this feature doesn't require it if you prefer long-hand coding.)



[TOPIC: post.html]
#7

rune7

[GLOBAL: userInfoPane.html]
rune7
  • Contributor

  • 353 posts
  • Corona SDK

@roaminggamer,

 

By works as expected you mean how davebollinger described? if so, than it is not what current documentation implies.

I'm familiar with the one way platform example. This is what led me down the wrong path. This example assumes a continuous existence of both objects. In your example, the preCollision check will not prevent the call to the collision event, thus my object will be destroyed instead of pass through the wall.

 

It will not help in the case I described earlier: 

Assume you have an object which either need to pass through the wall or be removed. where would you check for the condition and decide to either remove it from display or let it pass by disabling the contact?

 

My current thought is to disable contact if needed on the preCollision and destroy if needed on the postCollision. Its noisy but I don't see a better approach. It seems that the collision event should only be used when the situation is simple to save computation time.

Do you know of a better way to handle this situation?



[TOPIC: post.html]
#8

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,297 posts
  • Enterprise

you should "destroy" once you've determined the "fireball" actually interacts with a "killing wall" - which presumably happens in preCollision (because the one-way logic can't happen anywhere else - go ahead and try it if you like, but eventually you'll return to preCollision.event.contact.isEnabled)

 

iow, there's no point in "deferring" the destruction until postCollision (fe, set a "flag" in preCollision, then destroy in postCollision)

 

caveat:  this is assuming i've correctly understood your setup, and you need the fireball to "pass through" the first wall (ie, ignore the first collision) and then be destroyed by the second (btw, at which point the contact with the first wall would still exist, unless moving fast enough to tunnel through it in non-continuous mode)

 

>> In your example, the preCollision check will not prevent the call to the collision event

 

of course it doesn't, as this NEVER happens.  you CANNOT "prevent" the call to the collision event.  all you can do is prevent the response.  "collision" happens (necessarily) before "preCollision".  as i said before:  stop thinking in terms of Corona's event *names*, because they'll only confuse you if you do -- "preCollision" can only happen AFTER "collision".

 

maybe it helps to consider what a sensor is:  a sensor detects contacts, but never issues a solve.  THAT is what the preCollision.event.contact.isEnabled=false mimics when doing one-way platforms, it says "skip the response".   but note that the contact itself still occurs regardless!

 

>> Its noisy

 

"noisy" is a relative term.  the preCollision/postCollision events (aka "solve" events) fire more often (ie, per frame) because they are not persistent like the less-noisy collision event (aka "contact" event).  so while you'll only get one contact while moving through a wall, you'll get many solves (one pair per frame, for as many frames as it takes to get through, depending on relative velocity vs size of objects).



[TOPIC: post.html]
#9

rune7

[GLOBAL: userInfoPane.html]
rune7
  • Contributor

  • 353 posts
  • Corona SDK

Hi @davebollinger,

 

Yes, I understood that there is no point in waiting for the post collision to destroy it. The problem I had was that I had code in the collision event which must be relocated.

BTW, I found that I can also disable the contact in the collision event itself which can serve as alternate solution being less 'noisy'.



[TOPIC: post.html]
#10

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,297 posts
  • Enterprise

BTW, I found that I can also disable the contact in the collision event itself which can serve as alternate solution being less 'noisy'.

 

that should work for this specific case (where you're using the contact to immediately destroy an object) though it won't work for the more-general case of implementing one-way platforms (because you'll still get multiple pre/post solve events per-frame, throughout the duration of the contact, that must be individually disabled, despite the initial contact event being disabled) but perhaps that will suffice (it isn't entirely clear how your "dual-one-way platforms" are intended to function in the grand scheme).  again, "noisy" is relative - if you were to destroy the object on the first occurrence of a presolve event, then it's no-more-noisy than the contact event.




[topic_controls]
[/topic_controls]