Qt Quick 颗粒示例 - 影响#

这是一个使用 QML 颗粒系统影响器的示例集合。

../_images/qml-affectors-example.png

这是一个与在粒子系统中使用影响器相关的小型 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
}

场景中的所有粒子,包括火箭的尾气和弹丸,都会被黑洞吸引。这种效应在黑洞附近更强,因此屏幕顶部的陨石几乎不受影响,而中间的陨石有时会急剧弯曲。为了完成效果,可以使用 Age 影响器来覆盖黑洞,摧毁与它接触的粒子。

Custom Affector 直接在javascript中操作粒子的属性。一个影响器使叶子在落下时来回摇摆,看起来比只旋转在圈中更像叶子。

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 为在影响器内部的应用恒定加速度的粒子提供了一个便捷的影响器。

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

GroupGoal 为燃烧和非燃烧球设置了两个粒子组,并提供各种方式在不同组之间进行切换。

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

非燃烧球在一秒内有一百分之一的可能性自燃,但它们在全组上都有一个 GroupGoal。当未点亮的组的粒子与点亮组的粒子相碰撞时,这个影响器会影响未点亮组中的所有粒子,并使它们移动到点亮组。

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

点亮是一个中间组,这样光晕就可以逐渐积累,过渡就不会那么突兀。因此,它会自动在 100 毫秒后移动到点亮组。

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"

点亮组还附带轨迹发射器,以提供额外的火焰和烟雾,但不会转移到任何地方。还有两个 GroupGoal 对象,允许未点亮组的粒子转移到点亮组(然后转移到点亮组)。

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

第一个是一个与飞行员火焰图像的位置绑定的区域。当未点亮的球穿过火焰时,它们会直接移动到点亮,因为飞行员火焰非常热。

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

第二个是与最后指针交互的位置绑定的,因此在未点亮的球上触摸或点击(由于它们不断移动,这很难)会导致它们移动到点亮组。

Move 展示了一些通过改变轨迹中途获得的一些简单效果。红色粒子有一个影响器会影响它们的位置,将它们向前跳跃 120 像素。

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

蓝色粒子有一个影响其加速度的作用力,并且因为它相对于“假”设置,所以它重置加速度而不是增加加速度。一旦蓝色粒子达到作用力,它们的水平速度停止增加,而垂直速度减少。

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 {
    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 {
    id: wanderer
    system: particles
    anchors.fill: parent
    xVariance: 360/(wanderer.affectedParameter+1);
    pace: 100*(wanderer.affectedParameter+1);
}

通过将漫步应用于轨迹的不同属性,可以得到不同的运动,因此示例可以轻松地进行操作并观察差异。

示例项目 @ code.qt.io