1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
|
..
---------------------------------------------------------------------------
Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
All rights reserved.
This work, unless otherwise expressly stated, is licensed under a
Creative Commons Attribution-ShareAlike 2.5.
The full license document is available from
http://creativecommons.org/licenses/by-sa/2.5/legalcode .
---------------------------------------------------------------------------
Particles
=========
Overview
--------
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 :qt5:`Particles <qtquick/qtquick-particles2-qtquick-effects-particles.html>` module is based on four major components:
.. image:: images/particles-module.png
:align: center
:scale: 60%
* The ``ParticleSystem`` ties all the elements together and runs the system timers. ``Painters``, ``Emitters`` and `Affectors` should all have the same `ParticleSystem` to interact with each other.
* The :qt5:`PariclePainter <qtquick/qml-qtquick-particles2-particlepainter.html>` enables the rendering of particles that can be image items or custom shaders.
* The :qt5:`Emitter <qtquick/qml-qtquick-particles2-emitter.html>` emits the particle objects into the system from the location of the emitter itself and controls some particle properties (`lifeSpan`, `size` etc).
* The :qt5:`Affector <qtquick/qml-qtquick-particles2-affector.html>` is an optional type that alters the attributes of particles after being created in order to manipulate the simulation (for example, modifying the trajectroty, applying gravity effects, and so on).
Basic Setup
-----------
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 :qt5:`ImageParticle <qtquick/qml-qtquick-particles2-imageparticle.html>` to render particles based on an image, and an ``Emitter`` to create and emit particles.
.. code-block:: js
// 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.
.. image:: images/particles-1.png
:align: center
:scale: 60%
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 :qt5:`lifeSpan <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.
.. code-block:: js
Emitter {
height: 10; width: 10
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
Then we set the trajectory and speed of the particles using :qt5:`AngleDirection <qtquick/qml-qtquick-particles2-angledirection.html>` QML type.
.. code-block:: js
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:
.. code-block:: js
Emitter {
...
// 8 seconds may be enough
lifeSpan: 8000
}
We can also set the particles to emit in various sizes by using the :qt5:`sizeVariation <qtquick/qml-qtquick-particles2-emitter.html#sizeVariation-prop>` property in the ``Emitter`` component:
.. code-block:: js
Emitter {
...
// set the variation up to 5 pixels bigger or smaller
sizeVariation: 5
}
The :qt5:`colorVariation <qtquick/qml-qtquick-particles2-imageparticle.html#colorVariation-prop>` property in the ``ImageParticle`` type enables us to apply color variation to the particles:
.. code-block:: js
ImageParticle {
...
//Color is measured, per channel, from 0.0 to 1.0.
colorVariation: 1.0
}
Then we can use the :qt5:`Gravity <qtquick/qml-qtquick-particles2-gravity.html>` affector to make our particles fall back down.
.. code-block:: js
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.
.. image:: images/particles-2.png
:align: center
:scale: 60%
.. note:: The complete code is available in the `particles_example_02.qml` file.
ParticleGroups and Transitions
------------------------------
The `Particles` module also provides a :qt5:`ParticleGroup <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 :qt5:`TrailEmitters <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:
.. code-block:: js
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.
.. code-block:: js
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.
.. code-block:: js
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 :qt5:`GroupGoal <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.
.. code-block:: js
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.
.. code-block:: js
// 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:
.. image:: images/fireworks.png
:scale: 60%
:align: center
what's next?
------------
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`.
|