Bring your games to life with particles
AuthorLuka Leopoldović
DateJul 15, 2019
If you are a mobile game developer, or plan to develop a mobile game, then you are probably aware that using classic animation and sprites in your games may no longer do the trick.
Since the mobile hardware has gotten stronger, it can easily be utilized to produce much more effective and attractive results than the classic approach. What do I mean exactly? For example, if you are making an alien invasion game and have to show some fire, rain, thunder, fog, some special alien magic or even a meteor shower, using pre-built animations is a boring approach which may take a lot of time to build and is, most certainly, a static and restrictive form of animation. That means you are stuck with the animation you have pre-loaded in your game and altering it can be a challenging task – depending on the form of the pre-built animation. So, the question is clear – how to create dynamic, realistic and scalable animation that can be dynamically adapted to your needs, and not just in the way of size or speed, but also quantity, lifespan, motion, color and direction diversity…? That’s where a particle system comes to the rescue!
A quick intro
A particle system is a technique which enables you to recreate or simulate a certain phenomena by defining behavior rules for a group (large number) of small particles. Those rules may include several definitions, like geometry, physics or graphics of the particles. This technique is often used in game physics and motion graphics and is supported by many game engines. For this blog, I’ll use the Corona Game Engine to create particle implementation since I use this engine for most of my games. But don’t worry, the same principles can be easily applied to other game engines, so I’ll try to make the blog as universal as possible. At least considering the particles themselves.
Let’s dive into it
What’s a better way to start a particles show-off than with a meteor shower, right? Well, just a meteor – at least for now. So, if you have never seen particles in action, now is the chance to do so. In the video below, you can see a meteor I created using a particle system. Pretty awesome, right?
Now, the question is how was this achieved? Let’s talk about the requirements. There are two key things defining a particle effect. First – since every particle effect consists of large number of small particles, you need an image that will represent a single particle. Second – as this image will be multiplied in the effect simulation stage, you need to define properties that will be applied to each and every one of them.
The image
The image should never be too complex. Most often, it’s a simple, small shape – single-colored image with an optional alpha-gradient. For better performance, it should also be as small as possible, considering both the file size and the image size.
You should always adjust or pick the shape depending on the effect your are trying to create. In particular, the left image was used to create the meteor effect. If I used the right image to create the meteor, I would still get an interesting result, but it wouldn’t quite resemble a meteor in the way the left image effect does.
Quick tip for designers: you can create a stash of dozens of images of different shapes, sizes and gradients and try out many of them while creating the effect. Once you get the effect properties set-up, just replace the image and see if it better suits your design preferences.
Behavior rules – particle properties
Next, that image will be multiplied many times and it needs to behave in the way you tell it to. But, what do you tell it exactly? The properties applicable to a particle (or a group of particles) can be divided into three categories: geometric, graphical and physical ones.
Geometric properties include basic definitions like the start and finish size of a particle, start and finish rotation etc. It also includes setting the variances of the properties. Right from the start, it is obvious why particles are a dynamic and non-restrictive form of animation. The properties you define will be randomly generated within the defined intervals and used to create particles. Consequently, every generated particle will have a different start and finish size, rotation etc. Additionally, if you wish, you can also set a specific property variance interval to 0 to ensure the static behavior of a specific definition.
Graphical properties apply the color and the alpha/blend settings to particles. These definitions include setting up the properties like:
- start red/green/blue color
- start r/g/b color variance
- finish r/g/b color
- finish r/g/b color variance
- start alpha
- finish alpha
- alpha variance
- source blending
- destination blending
Pretty much, it’s a game you can play until you are satisfied with the results.
At this point, it would be great to make a distinction between a particle and an emitter. You can think of an emitter as the source of the particles that controls a particle system’s position and motion in 2D or 3D space. To make the distinction clear, it means there are certain properties that can be defined at the animation level. These would mainly be physical properties as the emitter is responsible for them. This enables you to define the particles as physical objects that will follow the motion rules you define:
- variances of the generated particles along the X, Y and Z axes
- maximum number of particles
- particle lifespan
- X, Y or Z axis gravity
- particle speed or speed variance
- radial or tangential acceleration
- min and max radius
- rotations per second
If you are interested in the complete set of attributes you can attach to a particle/emitter in the Corona Game Engine, take a look at this link.
Creating the effect
The effect itself is actually very easy to configure. You can simply adjust the values of the attributes by forming them in key-value pairs (I’ll show them below) or use the Particles Designer if you are a Mac user. So, you can simply create an effect by dragging the sliders left or right without having to bother with the actual meaning of the properties. Nevertheless, knowing the background definitely helps to create desired effects easier and faster. Specifically, the meteor is defined as the “gravity” type emitter with increased value of the X gravity property (vs. zero value Y gravity) which attracts the sparks (particles) from the center of the meteor in the positive X axis direction, so you get the illusion of meteor leaving the trail behind it. Since every particle has a different lifespan and lifespan variance, only a small number of them will be generated with a longer lifespan – these particles will be pulled the most from the center and ‘form the trail’. As for the other elements, that’s mostly just playing with the colors.
If you are using the Particles Designer, the output you’ll get is a JSON file. The meteor effect particle definition I created looks like this:
{
"configName":"meteor",
"textureFileName":"images/particles/meteor-particle.png",
"emitterType":0,
"maxParticles":200,
"duration":2,
"particleLifespan":0.4,
"particleLifespanVariance":0.3,
"speed":0,
"speedVariance":0,
"startParticleSize":50,
"finishParticleSize":25,
"startParticleSizeVariance":50,
"finishParticleSizeVariance":20,
"rotationStart":0,
"rotationEnd":0,
"rotationStartVariance":0,
"rotationEndVariance":0,
"sourcePositionVariancex":0,
"sourcePositionVariancey":10,
"startColorRed":1,
"startColorGreen":0,
"startColorBlue":0,
"startColorVarianceRed":0,
"startColorVarianceGreen":0,
"startColorVarianceBlue":0,
"finishColorRed":1,
"finishColorGreen":1,
"finishColorBlue":0,
"finishColorVarianceRed":0,
"finishColorVarianceGreen":0,
"finishColorVarianceBlue":0,
"startColorAlpha":0.62,
"finishColorAlpha":0,
"startColorVarianceAlpha":0,
"finishColorVarianceAlpha":0,
"blendFuncSource":770,
"blendFuncDestination":1,
"angle":0,
"angleVariance":0,
"gravityx":10,
"gravityy":0,
"minRadius":0,
"maxRadius":0,
"minRadiusVariance":0,
"maxRadiusVariance":0,
"radialAcceleration":0,
"radialAccelVariance":0,
"tangentialAcceleration":0,
"tangentialAccelVariance":0,
"rotatePerSecond":0,
"rotatePerSecondVariance":0,
Now comes the developer’s part. To implement particles into your game, you first have to load the particle definition.
local meteorParticlesFilePath = system.pathForFile( "particles/meteor.json" )
local meteorFile = io.open( meteorParticlesFilePath, "r" )
local meteorParticlesFileData = meteorFile:read( "*a" )
meteorFile:close()
local meteorEmitterParams = json.decode(meteorParticlesFileData)
As I said before, these can be key-value pairs as well. By doing that, you’ll find it much easier to alter the effect since every property can be easily reached and modified by the requirements of the game. For instance, if you are building an air hockey game and want to show an ice-chopping effect, you can (dynamically) emit the number of particles proportional to the force of the paddle hitting the puck. And that’s where the particles shine the most.
local iceChopEmitterParams = {
textureFileName = "images/particles/ice-chop-particle.png",
emitterType = 0,
maxParticles = 200,
-- ...
}
-- In a post collision listener:
iceChopEmitterParams.maxParticles = eventForce
local emitter = display.newEmitter( iceChopEmitterParams )
Now, you have to create an emitter object and position it on the screen. Don’t worry about the content positioning constants. You can find them in the meteor implementation code.
local emitter = display.newEmitter( meteorEmitterParams )
emitter.x = Global.screenWidth*.75 + Global.extraX
emitter.y = - Global.extraY
emitter:rotate(-45)
The created emitter object can be easily animated using the default transition library provided by the engine to move the effect through the (in my case) 2D space.
transition.to(emitter, {x = emitter.x - totalScreenWidth, y = Global.screenHeight + Global.extraY + 200, time = 2800})
It is very important to highlight that particles won’t be destroyed until their lifespan and duration passes – even though they left the screen. Therefore, you should always adapt the effect duration to the actual needs to free the memory and improve performance. If your game needs to have long-running effects and it’s possible to switch the scene while the effect is still running, you can manually destroy the emitter to prevent memory leaks by using the following call:
display.remove(emitter)
emitter = nil
Performance tips
As every particle effect is generated by multiplying the particle image and applying properties to each and every one of them, you should keep in mind and take care of both while creating effects. Too complex effects can easily affect performance, result in frame drops and ruin the gaming/user experience. To prevent that from happening, try to do the following things:
- use simple images to create effects
- make images as small as possible, considering both the file and the image size – even though the image size will depend on the intent of the effect
- use as few particles as possible to create the effect (try to reduce the maximum number of particles property as much as possible)
- test your game on older devices to see how it performs and additionally reduce the maximum number of particles and/or adjust the effect to eliminate frame drops
- properly remove emitters when switching the game scenes to free the memory and avoid memory leaks
- don’t over-exaggerate with the usage of particles – they are fun and awesome, but should be used wisely and responsibly
- many things still can and should be achieved using “the classic animation” approach
Where to go from here
As any other display object, a particle object can also be added a physics body. That way you could detect when meteors hit the ground and, for instance, emit some explosion effect. If you are interested to learn more about physics implementation in mobile games, as well as detecting collision events, take a look at my collision implementation blog. One more thing – keep in mind that emitters can also be attached to any other display object in the game, they can be additionally translated, rotated and scaled without altering its properties, so you definitely gain a lot of flexibility in regards to the effect manipulation.
Particles are one of those things that are extremely fun to play with, and since the implementation is not hard and it does not take a lot of work, it’s also a cool thing to experiment with – both from the design, as well as the development aspect. Even though you should not over-exaggerate with particle usage, a proper dose of the effect can definitely bring your game to another level.
Before we finish, I’ll leave you with the promised meteor shower -you can download the full code from my Github. Have fun playing with particles!