Qt Quick Particles Beispiele – Affektoren

Dies ist eine Sammlung von Beispielen zur Verwendung von Affektoren im QML-Partikelsystem.

Rote Kugeln schweben an einer blauen Flamme vorbei, wobei eine Kugel in Flammen steht

Dies ist eine Sammlung kleiner QML-Beispiele zur Verwendung von Affektoren im Partikelsystem. Jedes Beispiel ist eine kleine QML-Datei, die einen bestimmten Typ oder eine bestimmte Funktion hervorhebt.

„Age“ veranschaulicht die Verwendung eines „Age“-Affektors, um die Lebensdauer von Partikeln vorzeitig zu beenden.

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

Wenn Sie den Affektor über den Bildschirm bewegen, springen die Partikel in seinem Inneren (die noch nicht davon betroffen waren) zu einem Zeitpunkt nahe dem Ende ihrer Lebensdauer. Dadurch bleibt ihnen eine kurze Zeit, um auszublenden; würden Sie jedoch „lifeLeft“ auf 0 setzen (Standardwert), würden sie das Ende ihrer Lebensdauer sofort erreichen.

„Attractor“ demonstriert die Verwendung eines „Attractor“-Affektors zur Simulation eines Schwarzen Lochs

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

Alle Partikel in der Szene, einschließlich der Abgase und Pellets des Raumschiffs, werden zum Schwarzen Loch hin angezogen. Dieser Effekt ist umso stärker, je näher man dem Schwarzen Loch kommt, sodass die Asteroiden am oberen Bildschirmrand kaum beeinflusst werden, während diejenigen in der Mitte manchmal drastisch ihre Flugbahn ändern. Um den Effekt zu vervollständigen, bedeckt ein „Age“-Affektor das Schwarze Loch, um Partikel zu zerstören, die damit in Kontakt kommen.

Der „Custom Affector“ manipuliert die Eigenschaften der Partikel direkt in JavaScript. Ein Affektor wird verwendet, um die Blätter beim Fallen hin und her schwingen zu lassen, wodurch sie natürlicher wirken, als wenn sie sich nur im Kreis drehen:

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;
        }
    }
}

Ein weiterer wird verwendet, um den Blättern beim „Aufsetzen“ eine leicht variierende Reibung zu verleihen, damit sie natürlicher wirken:

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;
        }
    }
}

„Friction“ funktioniert ähnlich wie der benutzerdefinierte Affektor für fallende Blätter, verwendet jedoch anstelle von benutzerdefinierten Affektoren eine gleichmäßige Reibung über die gesamte Fallstrecke.

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

„Gravity“ ist ein Komfort-Affektor, der den darin enthaltenen Partikeln eine konstante Beschleunigung verleiht

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

GroupGoal richtet zwei Partikelgruppen für brennende und nicht brennende Kugeln ein und bietet verschiedene Möglichkeiten für den Übergang zwischen diesen.

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
    }
}

Die nicht brennenden Kugeln haben jede Sekunde eine Chance von eins zu hundert, von selbst zu entzünden, aber für die gesamte Gruppe ist außerdem ein „ GroupGoal “ (Zünd-Affektor) festgelegt. Dieser Affektor wirkt auf alle Partikel der nicht brennenden Gruppe, wenn sie mit Partikeln der brennenden Gruppe kollidieren, und bewirkt, dass sie in die brennende Gruppe übergehen.

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

„lighting“ ist eine Zwischengruppe, damit sich das Leuchten allmählich aufbaut und der Übergang weniger abrupt wirkt. Daher wechselt sie nach 100 ms automatisch in die Gruppe „lit“.

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"

Die „lit“-Gruppe verfügt zudem über „TrailEmitters“ für zusätzliches Feuer und Rauch, wechselt jedoch nicht in eine andere Gruppe. Es gibt zwei weitere „ GroupGoal “-Objekte, die es Partikeln der „unlit“-Gruppe ermöglichen, in die „lighting“-Gruppe (und anschließend in die „lit“-Gruppe) überzugehen.

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

Das erste ist lediglich ein Bereich, der an die Position eines Bildes einer Zündflamme gebunden ist. Wenn unbeleuchtete Kugeln die Flamme durchqueren, gelangen sie direkt in die „lit“-Gruppe, da die Zündflamme so heiß ist.

//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
}

Das zweite ist an die Position der letzten Zeigerinteraktion gebunden, sodass das Berühren oder Anklicken unbeleuchteter Kugeln (was aufgrund ihrer ständigen Bewegung schwierig ist) dazu führt, dass sie in die Beleuchtungsgruppe wechseln.

„Move“ zeigt einige einfache Effekte, die man erzielen kann, indem man die Flugbahn auf halbem Weg verändert. Die roten Partikel haben einen Affektor, der ihre Position beeinflusst und sie um 120 px nach vorne springen lässt.

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

Die grünen Partikel haben einen Affektor, der ihre Geschwindigkeit beeinflusst, allerdings mit einer gewissen Winkelabweichung. Indem ihrer bestehenden Vorwärtsgeschwindigkeit eine zufällige Geschwindigkeitskomponente in einer bestimmten Richtung hinzugefügt wird, beginnen sie, sich kegelförmig auszubreiten.

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

Die blauen Partikel haben einen Affektor, der ihre Beschleunigung beeinflusst, und da dieser auf „false“ gesetzt ist, wird die Beschleunigung zurückgesetzt, anstatt sie zu erhöhen. Sobald die blauen Partikel den Affektor erreichen, steigt ihre horizontale Geschwindigkeit nicht mehr an, während ihre vertikale Geschwindigkeit abnimmt.

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

SpriteGoal verfügt über einen Affektor, der mit der Sprite-Engine der Partikel interagiert, sofern diese als Sprites von „ ImageParticle “ gezeichnet werden.

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

SpriteGoal folgt dem Bild des Raketenschiffs auf dem Bildschirm, und wenn es mit Partikeln interagiert, die von ImageParticle als Sprites gezeichnet werden, weist es diese an, sofort in den Zustand „explodieren“ zu wechseln, was in diesem Fall die Animation darstellt, bei der der Asteroid in viele Teile zerbricht.

„Turbulence“ verfügt über eine Flamme mit Rauch, wobei beide Partikelsätze von einem „Turbulence“-Affektor beeinflusst werden. Dies erzeugt einen schwachen Windeffekt.

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}
}

Um die Windrichtung zu ändern, ersetzen Sie im Parameter „noiseSource“ ein Schwarz-Weiß-Rauschbild (derzeit wird eine Standard-Rauschquelle verwendet).

„Wander“ nutzt einen „Wander“-Effektor, um den herabfallenden Schneeflocken eine horizontale Drift zu verleihen.

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

Durch die Anwendung von „Wander“ auf verschiedene Attribute der Flugbahn ergeben sich unterschiedliche Bewegungen, sodass man im Beispiel leicht damit experimentieren und die Unterschiede erkennen kann.

Beispielprojekt @ 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.