This tutorial outlines how to handle collisions between LiquidFun particles and Box2D rigid bodies. Handling these collisions is essential to implement a more comprehensive and responsive scenario using LiquidFun physics.
If you haven't read the LiquidFun Essentials tutorial, please read it carefully so that you understand the basics of the LiquidFun system.
For this tutorial, we'll need to create, at the minimum, a ParticleSystem and another object with which the particles can collide:
local physics = require( "physics" ) physics.start() -- Create a platform local platform = display.newRect( display.contentCenterX, 350, 160, 40 ) physics.addBody( platform, "static" ) platform.rotation = 10 -- Create the particle system local testParticleSystem = physics.newParticleSystem( { filename = "particle.png", radius = 2, imageRadius = 4 }) local function onTimer() testParticleSystem:createParticle( { x = display.screenOriginX - 10, y = 100, velocityX = 80, velocityY = -200, color = { 1, 0.2, 0.4, 1 }, lifetime = 32.0, flags = { "water", "colorMixing", "fixtureContactListener" } }) end timer.performWithDelay( 20, onTimer, 40 )
Let's inspect this code in more detail:
Immediately after including and starting the physics engine, we create a static platform for the particles to collide with and rotate it 10 degrees so that we can watch the liquid flow off it.
Next we create the particle system using relatively basic properties.
With the particle system in place, we create a function (onTimer()
). Inside this function we include a call to the object:createParticle() method which generates a single particle. The properties for this call are similar to those in the LiquidFun Essentials tutorial except for the inclusion of one very important flag: "fixtureContactListener"
. If you omit this flag, you will not receive particle collision responses!
Finally, we queue a timer to generate 40 particles at an increment of 20 milliseconds.
To re-emphasize the point above, you must include "fixtureContactListener"
within the flags
table when creating a particle. If this flag is not included, you will not receive particle collision responses.
Now let's add a function to listen for collision events on the particle system. This is similar to the method of local collision handling between traditional physical objects described here — in this case, we just need to set up the function, set the particle system's particleCollision
property to reference the function, and then add an event listener of the "particleCollision"
type to the system.
local function particleSystemCollision( self, event ) if ( event.phase == "began" ) then print( "PARTICLE SYSTEM:", event.particleSystem ) end end testParticleSystem.particleCollision = particleSystemCollision testParticleSystem:addEventListener( "particleCollision" )
This provides a very basic collision framework, but in most cases you'll need more information to properly react to particle collisions. Fortunately, Corona provides a considerable amount of information as properties of the event
table of the particleSystemCollision
listener function. These include:
event.name
— The string "particleCollision"
.event.phase
— One of the typical collision phases of "began"
or "ended"
.event.object
— Reference to the object that the particle collided with.event.element
— The fixture index of the other object, relevant for multi-element bodies.event.particleSystem
— Reference to the parent ParticleSystem of the colliding particle.event.x
— The x position of the particle that's involved in the collision.event.y
— The y position of the particle that's involved in the collision.event.normalX
— The collision normal's x direction.event.normalY
— The collision normal's y direction.event.r
— The red color value of the particle.event.g
— The green color value of the particle.event.b
— The blue color value of the particle.event.a
— The alpha color value of the particle.An critical consideration when working with LiquidFun is that actions applied as a result of a particle collision can only be done upon the particle system as an entire object. In other words, when a single particle collides with another object, you can read any of the above properties but you can't set a property upon that specific particle, for example set its b
value
Alternatively, you can detect collisions on other objects instead of directly on the particle system. This may be more logical if you're designing a game with multiple particle systems and you prefer to detect collisions on one primary object like a player character.
In our existing example, we can achieve this by adding a collision listener to the platform object instead of the particle system. Inspect the difference:
local function objectCollision( self, event ) if ( event.phase == "began" ) then print( "OBJECT:", event.object ) end end platform.particleCollision = objectCollision platform:addEventListener( "particleCollision" )
Conveniently, this model also provides the same event
table properties listed above, so you can gather info about the specific particle involved in the collision, including the particle system which generated it.
Yet another way to handle particle collisions is a global Runtime
listener. This will detect collisions between particles and other physical objects at the global level.
local function onGlobalCollision( event ) if ( event.phase == "began" ) then print( "OBJECT:", event.object ) print( "PARTICLE SYSTEM:", event.particleSystem ) end end Runtime:addEventListener( "particleCollision", onGlobalCollision )
Hopefully this tutorial has illustrated how simple it is to detect collisions between LiquidFun particles and other physical objects. This feature should help take your