The LiquidFun physics system allows you to simulate faucets, pools, waves, streams, and other amazing
In LiquidFun, all liquids are represented by a particle system, meaning that a stream or pool is made up of many “particles” which interact together to simulate the desired effect. Each particle is round and they are the minimal unit of matter in a particle system. By default, a particle behaves as a liquid, but you can change the behavior of individual particles or groups of particles. You can also set particle properties like position, velocity, and color.
Particles defined by the LiquidFun framework are not related to
In Corona, you create a ParticleSystem object via the physics.newParticleSystem() function:
physics.newParticleSystem( params )
In this API, params
is a table of parameters with only one required element: the file name (filename
) of the particle image to render for each particle instance:
local physics = require( "physics" ) physics.start() local testParticleSystem = physics.newParticleSystem( { filename = "particle.png" })
However, to make your particle system behave better, you should specify a couple additional properties. At minimum, you should define the particle radius
to control the size of the particles which constitute the liquid effect. Another useful parameter is imageRadius
which, if defined, will instruct Corona to render the particle image at a different size than the physical body defined by radius
. Essentially, if imageRadius
is slightly larger than radius
, the particles will overlap somewhat, resulting in a more cohesive
local physics = require( "physics" ) physics.start() local testParticleSystem = physics.newParticleSystem( { filename = "particle.png", radius = 2, imageRadius = 4 })
The complete list of other parameters and their purpose is beyond the scope of this tutorial, so please refer to the documentation or the LiquidFun Programmer’s Guide for more information.
Once you have an established particle system, new particles are generated using the object:createParticle() method. This accepts a table of optional parameters which control the behavior of each generated particle, for example:
testParticleSystem:createParticle( { x = 0, y = 0, velocityX = 256, velocityY = 480, color = { 1, 0.2, 0.4, 1 }, lifetime = 32.0, flags = { "water", "colorMixing" } })
Most of these parameters are
x
and y
determine where the new particle is generated in content space.velocityX
and velocityY
specify the starting velocity values for the new particle.color
is a table of RGB+A values for the particle.lifetime
defines how many seconds the particle remains on screen before it dies.flags
can be either a string or a table of strings which dictate various behavioral aspects of the particle. These options are beyond the scope of this tutorial, so please refer to the LiquidFun Programmer’s Guide for more information.It’s important to note that object:createParticle() creates just one particle in the overall system, so to create a useful scenario, you’ll need to generate numerous particles by calling this function on a repeating timer or via some other repeating method. For instance:
local physics = require( "physics" ) physics.start() local testParticleSystem = physics.newParticleSystem( { filename = "particle.png", radius = 2, imageRadius = 4 }) local function onTimer( event ) testParticleSystem:createParticle( { x = 0, y = 0, velocityX = 256, velocityY = 480, color = { 1, 0.2, 0.4, 1 }, lifetime = 32.0, flags = { "water", "colorMixing" } }) end timer.performWithDelay( 20, onTimer, 0 )
In addition to creating single particles in a system, you can create groups of related particles using the object:createGroup() function. Essentially, this “fills” a defined region with multiple particles in one command and the group can be assigned various behavioral and visual properties. For example:
local physics = require( "physics" ) physics.start() local testParticleSystem = physics.newParticleSystem( { filename = "particle.png", radius = 2, imageRadius = 4 }) testParticleSystem:createGroup( { x = 0, y = 0, color = { 0, 0.3, 1, 1 }, halfWidth = 64, halfHeight = 32, flags = { "water", "colorMixing" } })
This code generates a rectangular particle group, but you can also create circular groups and arbitrary shape groups. Please refer to the documentation for information on creating different group types.
Linear force can be applied to the center of all particles in a particle system via the object:applyForce() API. This method accepts two numerical values indicating the amount of force to apply in the x and y directions respectively. For instance:
testParticleSystem:applyForce( 0, -9.8 * testParticleSystem.particleMass )
Alternatively, you can apply a linear impulse to all particles with the object:applyLinearImpulse() API. This is similar to the above method except that an impulse is a single momentary jolt in
testParticleSystem:applyLinearImpulse( 0, -9.8 * testParticleSystem.particleMass )
While generating individual particles and even groups of particles can provide for some amazing effects, at some point you may need to detect and manipulate particles within a defined region. This is accomplished via the object:queryRegion() function using the following syntax:
ParticleSystem:queryRegion( upperLeftX, upperLeftY, lowerRightX, lowerRightY, hitProperties )
The defined region must be rectangular and it’s defined by the first four parameters — simply specify the upperLeftX
/upperleftY
)lowerRightX
/lowerRightY
)
The last parameter, hitProperties
, is a table of optional properties which can be applied to each particle in the region. Valid properties include:
deltaX
— The x position delta to apply to each particle.deltaY
— The y position delta to apply to each particle.velocityX
— The x velocity delta to apply to each particle.velocityY
— The y velocity delta to apply to each particle.So, if you want to apply an upward y velocity to all particles in a region, the code may look like this:
local hits = testParticleSystem:queryRegion( 10, 40, 100, 160, { velocityY=-40 } )
All of the values potentially applied in the hitProperties
table are delta values that will be applied to each particle’s current associated value(s). For example, if you apply a velocityY
of -40
to the particles in the region, it does not directly set -40
as the actual y velocity on them, but rather it applies that velocity in delta relation to any existing velocity the particles already have.
Detecting collision events between LiquidFun particles and other physical objects is an
This tutorial is meant to be a brief introduction to LiquidFun physics in Corona, but the capabilities of the framework extend beyond this scope. Please consult the documentation or the LiquidFun Programmer’s Guide for more information.