Today’s tutorial introduces the Corona physics contact, a feature that was recently implemented within the physics engine. Generally speaking, a physics contact is a “reference to a specific collision that is about to occur.”
Developers familiar with the physics pre-collision might ask “how does a physics contact differ?”. While the physics contact will, in almost every case, be used during a pre-collision event, there are some important differences to note.
In a typical pre-collision (or any collision) between two objects, Corona allows you to access each object by Lua 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, allowing it to pass through the other object when the collision occurs. Or you might choose to destroy one of the objects, animate it, apply a specific force upon it, or any number of other actions. This has all been possible in Corona for a long time, but there are a few limitations that the physics contact can solve.
A common requirement in 2D side-view games is the “one-sided platform” such as those in Super Mario Brothers and a thousand other 2D platform games. The character can jump from beneath a platform, pass through the platform, and land nicely atop it. Previously, this was “solved” in Corona by changing 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 most cases, it presents at least one obvious problem. What if an enemy “goomba” is walking atop the platform? The character will still be a sensor when it collides with the enemy’s feet and will pass directly through! Similarly, what if the character collides with some other non-platform object during its upward trajectory toward the platform? Post-collision forces such as “bounce” would be lost.
Introducing the Physics Contact
The solution to the above dilemma can be solved with Corona’s new physics contact. As stated above, you can consider this as a specific reference to a collision that is about to occur. When used within a pre-collision event listener (typical usage), you can access the physics contact and four properties that weren’t previously 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!
Here’s how to access the physics contact in code, using a pre-collision event listener:
Notice that the physics 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 change the bounce/friction factor(s) for that specific collision, overriding the inherent bounce/friction that you declared for the object(s).
For a one-sided platform, the physics contact method is much better. You initially set a property of the platform as “pass through” (or any other term), and then, using conditional logic, you 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 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. 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.
In Corona, the physics contact (and its properties) can be accessed from any type of collision listener: pre-, post-, or standard. In most cases, you will access it from a pre-collision, because logically you need to access or set a property of a collision before it occurs, not when or after it occurs.
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 bumper for extreme bounce (set physics contact bounce to 1)
- Silver balls collide with blue bumper for no bounce (set physics contact bounce to 0)
- Gold balls collide with red bumper for no bounce (opposite of the first case)
- Gold balls collide with blue bumper for medium bounce
See it in Action
Check out this demo project to see the “one-sided platform” method in action, using physics contacts.
The new physics contact provides four new properties that can be accessed on a specific collision basis:
- event.contact.isTouching — read only: are the two objects touching?
- event.contact.isEnabled — read/write: ‘true’ or ‘false'; should the collision resolve?
- event.contact.bounce — read/write: get or set the bounce factor of the collision
- event.contact.friction — read/write: get or set the friction factor of the collision
In special circumstances, these properties allow a level of fine-tuned control that was not previously possible using basic collision events and collision filters. Give them a try in your next physics-based project and, as usual, please open up the conversation below with your questions, comments, and observations.