Qt Quick 2 comes with the Particles module for making nice visual particle effects, which can be used by many applications that require a lot of tiny moving particles such as fire simualtion, smoke, stars, music visualization, and so on.
The Particles [http://qt-project.org/doc/qt-5.0/qtquick/qtquick-particles2-qtquick-effects-particles.html] module is based on four major components:
Let’s start with a simple example that illustrates how we can use those different elements together to make particle effects.
The following example implements a simple rectangle with a ParticleSystem type that contains an ImageParticle [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-imageparticle.html] to render particles based on an image, and an Emitter to create and emit particles.
// particles_example_02.qml
import QtQuick 2.0
import QtQuick.Particles 2.0
Rectangle {
width: 360
height: 600
color: "black"
ParticleSystem {
anchors.fill: parent
// renders a tiny image
ImageParticle {
source: "resources/particle.png"
}
// emit particle object with a size of 20 pixels
Emitter {
anchors.fill: parent
size: 20
}
}
}
If you run the code shown above, you will see a couple of tiny particles (based on the image source) blinking on a black background.
The particles are emitted all over the entire area of the parent because we set the emitter’s anchors to fill the entire area of the root element (that is, the rectangle).
To make the animation more intersting, we may want to make all particles emit from the bottom of the window and spread out with an increased lifeSpan [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-emitter.html#lifeSpan-prop].
First we set the emitter’s anchors and specify where we want the particles to be emitted from.
Emitter {
height: 10; width: 10
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
Then we set the trajectory and speed of the particles using AngleDirection [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-angledirection.html] QML type.
Emitter {
...
velocity: AngleDirection {
// Make particles spread out vertically from the bottom
angle: 270
// make the movement of the particles slighly different from
// one another
angleVariation: 10
// set speed to 150
magnitude: 100
}
...
}
As the default lifeSpan for a particle is one second, we will increase its value so that we can visualize the particles path:
Emitter {
...
// 8 seconds may be enough
lifeSpan: 8000
}
We can also set the particles to emit in various sizes by using the sizeVariation [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-emitter.html#sizeVariation-prop] property in the Emitter component:
Emitter {
...
// set the variation up to 5 pixels bigger or smaller
sizeVariation: 5
}
The colorVariation [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-imageparticle.html#colorVariation-prop] property in the ImageParticle type enables us to apply color variation to the particles:
ImageParticle {
...
//Color is measured, per channel, from 0.0 to 1.0.
colorVariation: 1.0
}
Then we can use the Gravity [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-gravity.html] affector to make our particles fall back down.
ParticleSystem {
...
Gravity {
anchors.fill: parent
// apply an angle of acceleration when the particles hit
// the affector
angle: 90
// accelerate with 15 pisxels/second
acceleration: 15
}
...
}
If you now run the code, you will see an animation displaying particles of different sizes and colors spreading out from the bottom to the top of the window and then falling back down.
Note
The complete code is available in the particles_example_02.qml file.
The Particles module also provides a ParticleGroup [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-particlegroup.html] type that enables us to set timed transitions on particle groups. This could be very helpful if we want to implement animations with special behavior that require many transitions.
To illusrate how we can use ParticleGroup, let’s implement a simple fireworks animation. The particles should be emitted from the bottom of the window. We’ll also add some TrailEmitters [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-trailemitter.html] that simulates smoke produced by flames as well as explosions in mid-air.
In our fireworks animation we proceed as follows:
Within the main Rectangle, we add a ParticleSystem that will be used by all components to run the animation.
Add the main Emitter that emits firework particles from the buttom to the top of the window and specify a logical group identifier so that we can later assign an ImageParticle to render the flame particles.
Add a TrailEmitter that will simulate the smoke produced by the flame. We also specify a logical group so that we can later assign the corresponding ParticlePainter to the emitter.
Add a ParticleGroup to simulate the explosion using a TrailEmitter type.
Add a GroupGoal in the main Emitter to tell where or when to apply the transition we define in the ParticleGroup.
Note
A logical group enables us to paint particles emitted by different Emitters using different ImagePartilces within the same ParticleSystem as we will see later in the four seasons demo application.
So first, we declare one main Emitter that emits firework particles from the bottom to the top:
import QtQuick 2.0
import QtQuick.Particles 2.0
Rectangle {
width: 360
height: 600
color: "black"
// main particle system
ParticleSystem {id: particlesSystem}
// firework emitter
Emitter {
id: fireWorkEmitter
system: particlesSystem
enabled: true
lifeSpan: 1600
maximumEmitted: 6
// Specify the logical group that
// the emitter belongs to
group: "A"
// we want to emit particles
// from the bottom of the window
anchors{
left: parent.left
right: parent.right
bottom: parent.bottom
}
velocity: AngleDirection {
angle: 270
angleVariation: 10
magnitude: 200
}
}
}
Then we add a TrailEmitter type to simulate the smoke produced by the firework before exploding in the air.
TrailEmitter {
system: particlesSystem
group: "B"
// follow particle emitted by fireWorkEmitter
follow: "A"
size: 12
emitRatePerParticle: 50
velocity: PointDirection {yVariation: 10; xVariation: 10}
acceleration: PointDirection {y: 10}
}
Then we add a ParticleGroup type to set a transition and simulate the explosion of particles in the air. We will be using a TrailEmitter with an AngleDirection to display the exploding effect.
ParticleGroup {
name: "exploding"
duration: 500
system: particlesSystem
TrailEmitter {
group: "C"
enabled: true
anchors.fill: parent
lifeSpan: 1000
emitRatePerParticle: 80
size: 10
velocity: AngleDirection {angleVariation: 360; magnitude: 100}
acceleration: PointDirection {y: 20}
}
}
In order to know exactly where to apply the transition, we add a GroupGoal [http://qt-project.org/doc/qt-5.0/qtquick/qml-qtquick-particles2-groupgoal.html] type inside the fireWorkEmitter that tells the emitter what the aimed state is and when/where the particles should switch to it.
Emitter {
id: foreWorkEmitter
...
GroupGoal {
// on which group to apply
groups: ["A"]
// the goalState
goalState: "exploding"
system: particlesSystem
// switch once the particles reach the window center
y: - root.height / 2
width: parent.width
height: 10
// make the particles immediately move to the goal state
jump: true
}
}
Next, we just add the ImageParticle types to visualize particles for each group defined above.
// ParticlePainter for the main emitter
ImageParticle {
source: "resources/particle.png"
system: particlesSystem
color: "red"
groups: ["A"]
}
// ParticlePainter for the trailEmitter smoke
ImageParticle {
source: "resources/smoke_particle.png"
system: particlesSystem
groups: ["B"]
color: "white"
}
// ParticlePainter for the trailEmitter in the ParticleGroup
ImageParticle {
source: "resources/smoke_particle.png"
system: particlesSystem
groups: ["C"]
color: "red"
colorVariation: 1.2
}
And now if you run the code, you should have a simple animation that displays particles emitted from the window bottom and exploding once they reach the window center:
In the next article, we introduce the ShaderEffect type used for more advanced graphic effects. We will also implement a demo application that uses Particles and Shaders.