summaryrefslogtreecommitdiffstats
path: root/particles_tutorial/particles.rst
blob: c7e8c76a817c436630eac5c5271ecab2ebf3774a (plain)
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-qml-particlesystem.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`.