Qt Quick パーティクルの例 - アフェクター

QMLのパーティクルシステムでAffectorsを使用した例を集めたものです。

これは、パーティクルシステムでアフェクタを使うことに関連した、小さなQMLの例を集めたものです。それぞれの例は、特定のタイプや特徴を強調した小さなQMLファイルです。

Age」は、「Age」アフェクタを使ってパーティクルの寿命を早める例を示しています。

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

画面上でアフェクタを動かすと、その中のパーティクル(まだ影響を受けていないもの)が寿命の終わりに近い期間にジャンプします。これにより、フェードアウトが完了するまでの短い期間が与えられますが、lifeLeftを0(デフォルト)に変更すると、即座にライフが終了してしまいます。

Attractor は、ブラックホールをシミュレートするために Attractor アフェクタを使用することを示します。

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

ロケット船の排気やペレットを含むシーン内のすべてのパーティクルは、ブラックホールに向かって引っ張られます。このエフェクトはブラックホールに近いほど強くなるので、スクリーンの上部に近い小惑星はほとんど影響を受けませんが、中央の小惑星は時々大きくカーブします。この効果を完成させるために、エイジ・アフェクターがブラックホールを覆い、接触した粒子を破壊します。

カスタムアフェクタは、パーティクルのプロパティをjavascriptで直接操作します。1つのアフェクタは、葉っぱが落ちるときに前後に揺れ、ただ円を描いて回転しているよりも葉っぱらしく見えるようにするために使われます:

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

もうひとつは、葉っぱが「着地」するときの摩擦をわずかに変化させて、より自然に見せるために使います:

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 {
    anchors.fill: parent
    anchors.margins: -40
    factor: 0.4
}

重力は、内部のパーティクルに一定の加速度を加えるための便利なアフェクタです。

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

GroupGoal は、炎のあるボールと炎のないボールの2つのパーティクル グループを設定し、それらの間を遷移するさまざまな方法を提供します。

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

非発光ボールは毎秒100分の1の確率で単独で点灯しますが、グループ全体にGroupGoal 。この影響子は、非点灯グループのすべてのパーティクルに影響し、点灯グループのパーティクルと衝突すると、点灯グループに移動します。

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

lightingは中間的なグループなので、グローが蓄積され、遷移の衝撃が少なくなります。そのため、100ms後に自動的に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"

litグループには、追加の火と煙のためのTrailEmittersもありますが、どこにも遷移しません。さらに2つのGroupGoal オブジェクトがあり、非点灯グループのパーティクルが点灯グループに(そして点灯グループに)遷移できるようになっています。

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

1つ目は、パイロットの炎のイメージの位置にバインドされた領域です。点灯していないボールが炎を通過すると、パイロットの炎が非常に熱いため、そのまま点灯に移行します。

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

2つ目は、最後のポインタインタラクションの位置にバインドされており、点灯していないボールをタッチしたりクリックしたりすると(ボールが常に動くので難しいのですが)、点灯グループに移動します。

Moveは、軌道を途中で変更することで得られる簡単なエフェクトを示しています。赤いパーティクルには、位置に影響するエフェクタがあり、120px前方にジャンプします。

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

緑色のパーティクルには、速度に影響するアフェクタがありますが、角度によって変化します。既存の前方速度にランダムな方向速度を加えることで、円錐状に噴射し始めます。

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

青いパーティクルには加速度に影響するアフェクタがあり、falseに対して相対的に設定するため、加速度を追加する代わりにリセットします。青い粒子が影響子に到達すると、水平速度の増加は止まり、垂直速度は減少する。

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

SpriteGoal パーティクルが によってスプライトとして描画されている場合、パーティクルのスプライトエンジンと相互作用するアフェクタがあります。ImageParticle

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

SpriteGoal はスクリーン上のロケット船のイメージに従います。ImageParticle によってスプライトとして描画されたパーティクルと相互作用すると、「爆発」状態に即座に移動するように指示します。この場合、小惑星がたくさんの破片に割れるアニメーションです。

Turbulence には、煙を伴う炎があり、パーティクルの両方のセットが Turbulence エフェクタの影響を受けます。これはかすかな風のエフェクトを与えます。

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

風の向きを変えるには、noiseSource パラメータに白黒のノイズ画像を代入します(現在はデフォルトのノイズソースを使用しています)。

ワンダー(Wander) ワンダー(Wander)エフェクトを使って、雪の結晶が落ちるときに水平方向のドリフトを加えます。

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

軌跡のさまざまな属性にWanderを適用することで、さまざまな動きを与えることができます。

サンプルプロジェクト @ code.qt.io

© 2025 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.