Tutorial: Introducing physics “event.contact”

Share on Facebook0Share on Google+5Tweet about this on TwitterShare on LinkedIn0

Today’s tutorial introduces the Corona physics contact which, generally speaking, is a reference to a specific collision which is about to occur.

Pre-collision event

The physics contact will, in almost every case, be used during a pre-collision event, so you can handle the result of the collision before it actually occurs. In any collision event between two objects, Corona allows you to access each object by its Lua object ID. With those references, you might decide to perform an action on one (or both) objects. For example, you might change one object to a sensor, destroy one of the objects, animate it, apply a specific force upon it, etc. While these examples are all possible via a normal collision handler, the pre-collision event, along with the physics contact, can overcome certain unique scenarios.

One-sided platforms

A common requirement in 2D side-view games is the “one-sided platform” such as those in Super Mario Brothers and hundreds of other 2D platform games. The character can jump from beneath a platform, pass through the platform, and land nicely atop it.

One “solution” to this might be to change the character into a sensor at the beginning of a jump, such that it passes through the platform. Then, upon “exit” from the platform, the character is reverted back to a normal object. While this is an acceptable solution in some cases, it presents at least two obvious problems:

  1. What if an enemy “goomba” is walking atop the platform? In this case, the character will still be a sensor when it collides with the enemy’s feet, and the character will pass directly through both the platform and the enemy.
  2. What if the character collides with some other non-platform object during its upward trajectory toward the platform? In this case, normal collision forces such as “bounce” would be lost.

Introducing the physics contact

The solution to the above dilemma can be solved with a physics contact and a pre-collision handler. As stated at the beginning of this tutorial, you can consider the physics contact as a specific reference to a collision that is about to occur. Using this contact reference, you can access four properties that aren’t typically accessible.

Let’s consider the one-sided platform example again. When the character jumps and collides with the platform from below, Corona understands that a collision is about to occur between the character’s head and the bottom of the platform. Using a physics contact, you can gain temporary “access” to this upcoming collision and tell Corona how you’d like to handle it. You can even tell Corona to ignore it completely — and that is exactly what we need for the one-sided platform scenario.

Here’s how to access the physics contact in code, using a pre-collision event listener:

Notice that the physics contact (event.contact) provides you with collision-specific properties that you cannot access in a traditional listener events. Using basic conditional logic, you can then opt to ignore a collision entirely, or even change the bounce or friction factor(s) for that specific collision, overriding the standard bounce/friction that you declared for the object(s).

For a one-sided platform, this physics contact method is ideal. You can initially set a property of the platform as “pass through” (or any other term), and then, using conditional logic, tell Corona to ignore the collision entirely if the the platform is a "passthru" type, as in this example:

It’s important to note that the physics contact (event.contact) is not a reference to either object involved in the collision, but rather a reference to the collision itself. With that reference, you can opt to override the collision entirely — or just tweak a few optional properties of it — before it actually occurs. Also note that setting the physics contact properties does not permanently set those properties on either object involved — Corona only uses the properties for that specific collision, then it discards them. For example, if you change the bounce factor of the physics contact, it will not set/reset the core bounce factor on either object involved, but simply the bounce for that specific collision event.

Other possibilities

While the one-sided platform case is fairly common, there are other potential applications of the physics contact. For example, in a “pinball” game, you could use conditional logic (and physics contacts) to achieve the following:

  • Silver balls collide with red bumpers for extreme bounce (set contact bounce to 1)
  • Silver balls collide with blue bumpers for no bounce (set contact bounce to 0)
  • Gold balls collide with red bumpers for no bounce (opposite of the first case)
  • Gold balls collide with blue bumpers for medium bounce

Sample project

Check out the Corona PhysicsContact sample to see physics contacts and “one-sided platforms” in action.

In summary

The new physics contact provides four new properties that can be accessed on a specific collision basis:

In special circumstances, these properties allow a level of fine-tuned control that is not possible using basic collision events and collision filters.

Share on Facebook0Share on Google+5Tweet about this on TwitterShare on LinkedIn0

Brent Sorrentino serves as a full-time Developer Evangelist for Corona Labs, assisting developers in the forums, maintaining documentation/guides, and creating samples which highlight core features of Corona SDK.

This entry has 15 replies

  1. Joakim says:

    Thats great stuff and a very nice demo to check the new feature out!

    Keep it up!


  2. Matt says:

    Does this that we’re closer to collision location data?

    • Brent Sorrentino says:

      Hi Matt,
      I thought that PhysicsContact would be the solution, but apparently it’s not. However, I sincerely am investigating this collision bug and I’m seeking a resolution a.s.a.p. So, please be patient a bit longer. 🙂

      • james says:

        HAHAHA…my brother just spent hours a day for over a week working with me on this very issue. i’m a programmer, he’s not; he’s a physics major though. our solution was to work out the platform’s vertices and the bullet’s angle from the player, and use doLinesIntersect from the math library. it was hell.

        if you do solve this, you’re awesome! however, there is also the problem of bullets being effected by gravity. please help with this as well!

        • Brent Sorrentino says:

          Hi James,
          Good to hear this has helped you out!… at least mostly. Are the bullets in your scenario supposed to obey the same “pass through” laws on the platforms/obstacles? Or are they supposed to bounce off them?

      • james says:

        any word on the collision location data? my brother’s fix is accurate, but very buggy.

  3. sam3dus says:

    This is great news and will make our testing much easier.

    But how do you use this with a spawn + table function?

    balls = { }
    function spawnBall ()
    local ball etc
    –add to balls table etc

    ball:addEventListener( “preCollision” ) — throws the expected assertion error


    function ball:preCollision( event )

    • Brent Sorrentino says:

      You can achieve this by using “local” pre-collisions. Replace the global function “char:preCollision” in the demo project with this local function (internal contents remain the same):

      local function preCollision( self, event )


      And then add a local collision listener to each ball in your scenario:

      ball.preCollision = preCollision
      ball:addEventListener( “preCollision”, ball )

      That should work. And thanks for bringing this topic to my attention; certainly its a useful method if there are many objects following this preCollision behavior.

      • sam3dus says:

        Thanks for the reply. Don’t why I thought it required something other than the usual approach.

        Anyhow, this:

        function onLocalPreCollision( self, event ) — can’t use local on this function

        print( “enabled ” .. event.contact.isEnabled )

        Throws this error
        Build: 2012.971
        Runtime error
        d:\coronasdk\game\main.lua:616: attempt to concatenate field ‘isEnabled’ (a boolean value)

        Also, imho, adding the four new properties to ‘self’ would easily be as useful as your adding them to ‘event’

        • Brent Sorrentino says:

          Your error is a concatenation error, not an error with the event.contact. For some reason (I have never determined why), Lua occasionally gripes when you try to concatenate two items. Instead of concatenating them, just type it like:

          print( “enabled”, event.contact.isEnabled )

          • sam3dus says:

            Thanks for that info.

            Everything is working great now and event.contact is making things a lot easier for us.

  4. Finally! Thanks, Corona.

  5. Pablo Isidro says:

    Thank you so much!

    I’ve changed a many things in my project and this tutorial has made me all more easy!
    Cheers from Canary Islands 🙂

  6. Sat says:

    Ah, this is such a brilliant yet simple tutorial, thank you!