Qt Quick Exemples de particules - Affecteurs

Il s'agit d'une collection d'exemples utilisant les affecteurs dans le système de particules QML.

Il s'agit d'une collection de petits exemples QML relatifs à l'utilisation des Affectors dans le système de particules. Chaque exemple est un petit fichier QML mettant l'accent sur un type ou une caractéristique particulière.

Age démontre l'utilisation d'un affector Age pour mettre fin prématurément à la vie des particules.

Age {
    anchors.fill: parent
    system: particles
    once: true
    lifeLeft: 1200
    advancePosition: false
}

Lorsque vous déplacez l'affect sur l'écran, les particules qu'il contient (et qui n'ont pas encore été affectées) passent à une période proche de la fin de leur vie. Cela leur donne une courte période pour finir de s'éteindre, mais en changeant lifeLeft à 0 (la valeur par défaut), elles atteindraient instantanément la fin de leur vie.

Attractor démontre l'utilisation d'un affectateur Attractor pour simuler un trou noir.

Attractor {
    id: gs; pointX: root.width/2; pointY: root.height/2; strength: 4000000;
    affectedParameter: Attractor.Acceleration
    proportionalToDistance: Attractor.InverseQuadratic
}

Toutes les particules de la scène, y compris les gaz d'échappement de la fusée et les granulés, sont attirées vers le trou noir. Cet effet est d'autant plus fort que l'on se rapproche du trou noir, de sorte que les astéroïdes situés en haut de l'écran sont à peine affectés, tandis que ceux situés au milieu se courbent parfois de façon spectaculaire. Pour compléter l'effet, un affectateur Age recouvre le trou noir pour détruire les particules qui entrent en contact avec lui.

Custom Affector manipule les propriétés des particules directement en javascript. Un affectateur est utilisé pour que les feuilles se balancent d'avant en arrière lorsqu'elles tombent, ce qui leur donne l'air de ressembler davantage à des feuilles qu'à de simples cercles :

Affector {
    width: parent.width
    height: parent.height - 100
    onAffectParticles: (particles, dt) => {
        //Wobbly movement
        for (var i=0; i<particles.length; i++) {
            var particle = particles[i];
            particle.rotation += particle.vx * 0.15 * dt;
            particle.update = true;
        }
    }
}

Un autre est utilisé pour faire varier légèrement la friction des feuilles lorsqu'elles "atterrissent", afin de leur donner un aspect plus naturel :

Affector {//Custom Friction, adds some 'randomness'
    x: -60
    width: parent.width + 120
    height: 100
    anchors.bottom: parent.bottom
    onAffectParticles: (particles, dt) => {
        for (var i=0; i<particles.length; i++) {
            var particle = particles[i];
            var pseudoRand = (Math.floor(particle.t*1327) % 10) + 1;
            var yslow = dt * pseudoRand * 0.5 + 1;
            var xslow = dt * pseudoRand * 0.05 + 1;
            if (particle.vy < 1)
                particle.vy = 0;
            else
                particle.vy = (particle.vy / yslow);
            if (particle.vx < 1)
                particle.vx = 0;
            else
                particle.vx = (particle.vx / xslow);
            particle.update = true;
        }
    }
}

Le frottement est similaire à celui des feuilles qui tombent dans l'affect personnalisé, sauf qu'il utilise un frottement plat tout au long de la chute au lieu des affectations personnalisées.

Friction {
    anchors.fill: parent
    anchors.margins: -40
    factor: 0.4
}

La gravité est un affector de commodité pour appliquer une accélération constante aux particules à l'intérieur.

Gravity {
    system: sys
    magnitude: 32
    angle: ground.rotation + 90
}

GroupGoal met en place deux groupes de particules pour les boules enflammées et les boules non enflammées, et vous donne plusieurs façons de passer de l'un à l'autre.

ParticleGroup {
    name: "unlit"
    duration: 1000
    to: {"lighting":1, "unlit":99}
    ImageParticle {
        source: "images/particleA.png"
        colorVariation: 0.1
        color: "#2060160f"
    }
    GroupGoal {
        whenCollidingWith: ["lit"]
        goalState: "lighting"
        jump: true
    }
}

Les boules non enflammées ont une chance sur cent de s'allumer toutes seules à chaque seconde, mais elles ont aussi un affect GroupGoal sur l'ensemble du groupe. Cet affect affecte toutes les particules du groupe non éclairé, lorsqu'elles entrent en collision avec des particules du groupe éclairé, et les fait passer dans le groupe éclairé.

ParticleGroup {
    name: "lighting"
    duration: 100
    to: {"lit":1}
}

L'éclairage est un groupe intermédiaire qui permet à la lueur de s'accumuler et à la transition d'être moins brutale. Il se déplace donc automatiquement dans le groupe illuminé après 100 ms.

ParticleGroup {
    name: "lit"
    duration: 10000
    onEntered: root.score++
    TrailEmitter {
        id: fireballFlame
        group: "flame"

        emitRatePerParticle: 48
        lifeSpan: 200
        emitWidth: 8
        emitHeight: 8

        size: 24
        sizeVariation: 8
        endSize: 4
    }

    TrailEmitter {
        id: fireballSmoke
        group: "smoke"

Le groupe illuminé contient également des TrailEmitters pour plus de feu et de fumée, mais il n'y a pas de transition. Il existe deux autres objets GroupGoal qui permettent aux particules du groupe non éclairé de passer au groupe éclairé (puis au groupe éclairé).

GroupGoal {
    groups: ["unlit"]
    goalState: "lit"
    jump: true
    system: particles
    x: -15
    y: -55
    height: 75
    width: 30
    shape: MaskShape {source: "images/matchmask.png"}
}

Le premier est simplement une zone liée à l'emplacement d'une image de flamme pilote. Lorsque des boules non éclairées traversent la flamme, elles passent directement au groupe éclairé car la flamme pilote est très chaude.

//Click to enflame
GroupGoal {
    groups: ["unlit"]
    goalState: "lighting"
    jump: true
    enabled: ma.pressed
    width: 18
    height: 18
    x: ma.mouseX - width/2
    y: ma.mouseY - height/2
}

La seconde est liée à l'emplacement de la dernière interaction du pointeur, de sorte qu'en touchant ou en cliquant sur des boules non allumées (ce qui est difficile en raison de leur mouvement constant), elles se déplacent vers le groupe des boules allumées.

Move montre quelques effets simples que l'on peut obtenir en modifiant la trajectoire à mi-chemin. Les particules rouges ont un affector qui affecte leur position, les faisant avancer de 120px.

Affector {
    groups: ["A"]
    x: 120
    width: 80
    height: 80
    once: true
    position: PointDirection { x: 120; }
}

Les particules vertes ont un affectateur qui affecte leur vitesse, mais avec une variation d'angle. En ajoutant une vitesse de direction aléatoire à leur vitesse de déplacement vers l'avant, elles commencent à se projeter dans un cône.

Affector {
    groups: ["B"]
    x: 120
    y: 240
    width: 80
    height: 80
    once: true
    velocity: AngleDirection { angleVariation:360; magnitude: 72 }
}

Les particules bleues ont un affect qui affecte leur accélération, et parce qu'il est relatif à false, il réinitialise l'accélération au lieu de l'augmenter. Une fois que les particules bleues ont atteint l'affect, leur vitesse horizontale cesse d'augmenter tandis que leur vitesse verticale diminue.

Affector {
    groups: ["C"]
    x: 120
    y: 400
    width: 80
    height: 120
    once: true
    relative: false
    acceleration: PointDirection { y: -80; }
}

SpriteGoal a un affector qui interagit avec le moteur de sprites des particules, si elles sont dessinées en tant que sprites par ImageParticle.

SpriteGoal {
    groups: ["meteor"]
    system: sys
    goalState: "explode"
    jump: true
    anchors.fill: rocketShip
    width: 60
    height: 60
}

Le site SpriteGoal suit l'image de la fusée à l'écran et, lorsqu'il interagit avec les particules dessinées par ImageParticle sous forme de sprites, il leur demande de passer immédiatement à l'état "exploser", qui, dans ce cas, est l'animation de l'astéroïde se brisant en plusieurs morceaux.

Turbulence a une flamme avec de la fumée, et les deux ensembles de particules sont affectés par un affectateur de Turbulence. Cela donne un léger effet de vent.

Turbulence {
    id: turb
    enabled: true
    height: (parent.height / 2) - 4
    width: parent.width
    x: parent. width / 4
    anchors.fill: parent
    NumberAnimation on strength{from: 16; to: 64; easing.type: Easing.InOutBounce; duration: 1800; loops: -1}
}

Pour que le vent change de direction, substituez une image de bruit en noir et blanc dans le paramètre noiseSource (il utilise actuellement une source de bruit par défaut).

Wander utilise un affector Wander pour ajouter une dérive horizontale aux flocons de neige lorsqu'ils tombent.

Wander {
    id: wanderer
    system: particles
    anchors.fill: parent
    xVariance: 360/(wanderer.affectedParameter+1);
    pace: 100*(wanderer.affectedParameter+1);
}

L'application de l'affector Wander à différents attributs de la trajectoire permet d'obtenir des mouvements différents, l'exemple permet donc de jouer et de voir la différence.

Exemple de projet @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.