Qt Quick Particles Ejemplos - Afectores

Esta es una colección de ejemplos usando Afectores en el sistema de partículas QML.

Esta es una colección de pequeños ejemplos QML relacionados con el uso de Afectores en el sistema de partículas. Cada ejemplo es un pequeño archivo QML que enfatiza un tipo o característica particular.

Edad demuestra el uso de un afector Edad para terminar prematuramente la vida de las partículas.

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

A medida que mueves el afector por la pantalla, las partículas dentro de él (que aún no han sido afectadas) saltan a un periodo cercano al final de su vida. Esto les da un corto periodo para terminar de desvanecerse, pero cambiando lifeLeft a 0 (por defecto), causaría que alcanzaran el final de su vida instantáneamente.

Attractor demuestra el uso de un afector Attractor para simular un agujero negro

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

Todas las partículas de la escena, incluyendo el escape del cohete y las bolitas, son atraídas hacia el agujero negro. Este efecto es más fuerte cerca del agujero negro, por lo que los asteroides situados cerca de la parte superior de la pantalla apenas se ven afectados, mientras que los situados hacia el centro a veces se curvan drásticamente. Para completar el efecto, un afector de Edad cubre el agujero negro para destruir las partículas que entran en contacto con él.

El Afector Personalizado manipula las propiedades de las partículas directamente en javascript. Un afector se utiliza para hacer que las hojas se balanceen hacia adelante y hacia atrás mientras caen, pareciendo más hojas que simplemente girando en círculos:

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

Otro se utiliza para proporcionar una fricción ligeramente variable a las hojas cuando "aterrizan", para que parezcan más naturales:

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

La fricción es similar a la caída de las hojas en el afector personalizado, excepto que utiliza una fricción plana en todo el camino hacia abajo en lugar de afectores personalizados.

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

Gravedad es un afector de conveniencia para aplicar una aceleración constante a las partículas en su interior

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

GroupGoal Establece dos grupos de partículas para bolas llameantes y no llameantes, y te da varias formas de transición entre ellas.

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

Las bolas no flameantes tienen una probabilidad entre cien de encenderse por sí solas cada segundo, pero también tienen un GroupGoal establecido en todo el grupo. Este afector afecta a todas las partículas del grupo no iluminado, cuando colisionan con partículas del grupo iluminado, y hace que se muevan al grupo de iluminación.

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

La iluminación es un grupo intermedio para que el brillo se acumule y la transición sea menos brusca. Así que se mueve automáticamente en el grupo iluminado después de 100ms.

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"

El grupo iluminado también tiene TrailEmitters en él para el fuego y el humo adicional, pero no la transición en cualquier lugar. Hay dos objetos más en GroupGoal que permiten que las partículas del grupo no iluminado pasen al grupo iluminado (y luego al grupo iluminado).

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

El primero es sólo un área ligada a la ubicación de una imagen de una llama piloto. Cuando las bolas no iluminadas atraviesan la llama, pasan directamente al grupo iluminado porque la llama piloto está muy caliente.

//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 segunda está ligada a la ubicación de la última interacción con el puntero, de modo que tocar o hacer clic en las bolas no encendidas (lo que es difícil debido a su constante movimiento) hace que se muevan al grupo de iluminación.

Mover muestra algunos efectos simples que puedes conseguir alterando la trayectoria a mitad de camino. Las partículas rojas tienen un afector que afecta a su posición, haciéndolas saltar 120px hacia delante.

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

Las partículas verdes tienen un afector que afecta a su velocidad, pero con alguna variación de ángulo. Añadiendo un poco de velocidad de dirección aleatoria a su velocidad existente hacia delante, empiezan a salir pulverizadas en forma de cono.

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

Las partículas azules tienen un afector que afecta a su aceleración, y debido a que se establece en relación con falso esto restablece la aceleración en lugar de añadir a ella. Una vez que las partículas azules alcanzan el afector, su velocidad horizontal deja de aumentar a medida que disminuye su velocidad vertical.

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

SpriteGoal tiene un afector que interactúa con el motor de sprites de las partículas, si están siendo dibujadas como sprites por ImageParticle.

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

El SpriteGoal sigue la imagen del cohete en pantalla, y cuando interactúa con las partículas dibujadas por ImageParticle como sprites, les ordena moverse inmediatamente al estado "explotar", que en este caso es la animación del asteroide rompiéndose en muchos pedazos.

Turbulencia tiene una llama con humo, y ambos conjuntos de partículas siendo afectadas por un afector de Turbulencia. Esto da un efecto de viento débil.

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

Para hacer que el viento cambie de dirección, sustituye una imagen de ruido en blanco y negro en el parámetro noiseSource (actualmente utiliza una fuente de ruido por defecto).

Wander utiliza un afector Wander para añadir un poco de deriva horizontal a los copos de nieve a medida que caen.

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

Hay diferentes movimientos dados por la aplicación del Wander a diferentes atributos de la trayectoria, por lo que el ejemplo hace que sea fácil jugar y ver la diferencia.

Proyecto de ejemplo @ 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.