文章目录
一、前言
粒子系统用于模拟一些特定的模糊效果,例如:爆炸、烟花、雪花、水流等。使用传统的渲染技术实现粒子效果比较困难,但是使用QML粒子系统能十分方便的实现各种粒子效果,使你的界面更加炫酷、动感。
二、QML中的粒子系统
QML粒子系统的核心是ParticleSystem
,用于控制共享时间线。一个场景可以有多个粒子系统,每一个都有自己独立的时间线。
粒子由粒子发射器(Emitter
)元素发射,使用粒子画笔(ParticlePainter
)进行可视化显示,它可以是一张图片、一个QML项或者一个着色器程序。Emitter
还使用向量空间定义了粒子方向,粒子一旦发射,就脱离了Emitter
的控制。
粒子模块提供了粒子控制器(Affector
),它可以控制已发射粒子的参数。
系统中的粒子可以通过粒子组(ParticleGroup
)共享时间变换,默认情况下,粒子都属于空组。
粒子系统主要类如下:
类 | 功能 |
---|---|
ParticleSystem | 粒子系统,管理发射器共享时间线 |
Emitter | 粒子发射器,向系统中发射逻辑粒子 |
ParticlePainter | 粒子画笔,使用粒子画笔绘制粒子 |
Direction | 方向,已发出粒子使用的空间向量 |
ParticleGroup | 粒子组,每个粒子都是一个粒子组的成员 |
Affector | 粒子控制器,控制已发射的粒子 |
三、粒子系统-ParticleSystem
ParticleSystem
用于控制共享时间线,它将ParticleSystem
、Emitter
、Affector
等元素联合起来实现粒子效果,也就是说其它类型想要交互的话就必须在同一个ParticleSystem
中。
想要使用粒子系统,第一步就是要创建一个粒子系统:
import QtQuick.Particles 2.0
ParticleSystem {
id: particleSystem;
}
ParticleSystem包含以下属性:
属性 | 说明 |
---|---|
empty | 表示系统中是否还有活着的粒子 |
particleStates | 粒子动画状态,你可以给每一个粒子组的每一个粒子使用动画精灵 |
paused | 粒子系统是否暂停 |
running | 粒子系统是否在运行 |
ParticleSystem提供以下方法:
方法 | 说明 |
---|---|
void pause() | 暂停粒子系统 |
void reset() | 丢弃所有已经发射的粒子 |
void restart() | 停止所有粒子系统,并重新启动 |
void resume() | 当粒子系统处于暂停状态时,恢复粒子系统运行 |
void start() | 启动粒子系统 |
void stop() | 关闭粒子系统 |
四、粒子发射器-Emitter
Emitter
向粒子系统中发射逻辑粒子,这些粒子斗殴自己的轨迹和生命周期,但它们时不可见的,想要可见的话就得用到ParticlePainter
。
Emitter
定义了粒子的发射区域以及相关发射参数并使用system
属性将自己与一个粒子系统关联起来。
想要使用粒子系统,第二步就是要创建一个粒子发射器:
import QtQuick.Particles 2.0
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
system: particleSystem;
}
Emitter包含以下属性:
属性 | 说明 |
---|---|
acceleration | 粒子的起始加速度 |
emitRate | 发射速率(每秒发射多少个粒子,默认值为10) |
enabled | 发射器是否使能(默认值为true) |
endSize | 粒子什么周期结束时大小(默认值为-1) |
group | 逻辑粒子群(默认为“”,空字符串) |
lifeSpan | 粒子生命周期,单位毫秒(默认值为1000) |
lifeSpanVariation | 粒子生命周期误差区间 |
maximumEmitted | 粒子最大发射量 |
shape | 粒子发射的区域(默认值为Emitter的填充矩形) |
size | 粒子初始大小 |
sizeVariation | 粒子初始大小误差区间 |
startTime | 延迟发射时间 |
system | 粒子系统 |
velocity | 粒子发射速率 |
velocityFromMovement | 粒子的发射速率会叠加Emitter运动的速率 |
Emitter提供以下方法:
方法 | 说明 |
---|---|
void burst(int count, int x, int y) | 立即向(x,y)点发射count个粒子 |
void burst(int count) | 立即发射count个粒子 |
void pulse(int duration) | 当发射器未启用时,零食启动发射器duration毫秒 |
QML还提供一个叫
TrailEmitter
的发射器,该发射器的特点是起始位置是基于其它粒子的,它会跟随一个粒子移动。例如你需要创建一个跟随一团火焰的烟,你可能就需要用到这个发射器。
五、粒子画笔-ParticlePainter
使用Emitter
发射的只是逻辑粒子,我们还需要使用粒子画笔ParticlePainter
对粒子进行可视化渲染。ParticlePainter
是个基本类型,本身并不渲染任何东西,我们需要使用ParticlePainter
的子类进行渲染。ParticlePainter
的子类包括:ItemParticle
、ImageParticle
、CustomParticle
;
1、ItemParticle
ItemParticle
使用QML的Item来渲染粒子,我们可以给ItemParticle
的delegate(代理)属性设置一个Item,这样每个粒子都会使用该Item进行渲染。同样,我们也需要使用ItemParticle
的system
属性将ParticleSystem
与ItemParticle
关联起来。
import QtQuick.Particles 2.0
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
system: particleSystem;
}
ItemParticle {
system: particleSystem;
delegate: Rectangle{};
}
ItemParticle包含以下属性:
属性 | 说明 |
---|---|
delegate | 将为每个逻辑粒子创建委托实例,并随之移动 |
fade | 粒子是否在生命周期结束时自动淡出或淡出 |
ItemParticle提供以下方法:
方法 | 说明 |
---|---|
void freeze(Item item) | 暂停逻辑粒子代表的时间流,允许您控制它的移动 |
void give(Item item) | 获取Item的控制权,该Item将断开和逻辑粒子的关联 |
void take(Item item, bool prioritize) | |
void unfreeze(Item item) | 重新启动项目表示的逻辑粒子的时间流,允许它再次被粒子系统移动 |
2、ImageParticle
ImageParticle
使用图像来渲染逻辑粒子,图像能够上色、旋转、变形或者添加精灵动画。
ImageParticle包含以下属性:
属性 | 说明 |
---|---|
alpha | 图像的alpha值(0-1.0) |
alphaVariation | 图像的alpha值误差区间 |
autoRotation | 自动旋转 |
redVariation | 图像红色通道变化(0-1) |
greenVariation | 图像绿色通道变化(0-1) |
blueVariation | 图像蓝色通道变化(0-1) |
color | 图像颜色 |
colorTable | 纹理图像,原图像将与纹理图像混合 |
colorVariation | 图像颜色误差区间 |
entryEffect | 粒子创建和消失时的特效 |
opacityTable | 纹理图像,图像的opacity属性将与纹理图像混合 |
rotation | 图像旋转角度 |
rotationVariation | 图像旋转角度误差区间 |
rotationVelocity | 图像旋转速率 |
rotationVelocityVariation | 图像旋转速率误差区间 |
sizeTable | 纹理图像 |
source | 图像 |
sprites | 精灵动画 |
spritesInterpolate | 平滑精灵动画 |
status | 加载图像的状态 |
xVector | StochasticDirection |
yVector | StochasticDirection |
3、CustomParticle
除了ItemParticle
和ImageParticle
,还有基于着色器的粒子CustomParticle
,CustomParticle
使用OpenGL着色器语言GLSL定义。
CustomParticle包含以下属性:
属性 | 说明 |
---|---|
fragmentShader | 片段着色器 |
vertexShader | 顶点着色器 |
六、使用案例
1、用ItemParticle渲染粒子
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
Rectangle {
id: emitter_area;
anchors.centerIn: parent;
width: 200;
height: 200;
border.color: "green";
}
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.centerIn: parent;
width: 200;
height: 200;
system: particleSystem;
emitRate: 100;
lifeSpan: 1000;
lifeSpanVariation: 500;
size: 16;
endSize: 32;
}
ItemParticle {
system: particleSystem;
delegate: Rectangle {
id: particleRect;
width: 10;
height: 10;
color: "red";
radius: 10;
}
}
}
}
- 矩形元素
emitter_area
和粒子发射器Emitter
完全重合,可以看到粒子也只在这个区域内产生,说明粒子只会在粒子发射器限定的范围内产生;
2、用ImageParticle渲染粒子
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.centerIn: parent;
width: 200;
height: 200;
system: particleSystem;
emitRate: 20;
lifeSpan: 1000;
lifeSpanVariation: 500;
size: 16;
endSize: 32;
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
}
}
}
3、用ImageParticle渲染粒子,并设置粒子颜色
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.centerIn: parent;
width: 200;
height: 200;
system: particleSystem;
emitRate: 10;
lifeSpan: 2000;
lifeSpanVariation: 500;
size: 16;
endSize: 32;
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
}
}
}
- 给粒子画笔
ImageParticle
设置了color为金色,颜色误差设置为0.6(颜色误差设置越靠近0误差越小,基本都是金色;颜色误差设置越靠近1误差越大,颜色越随机);
4、用ImageParticle渲染粒子,并设置粒子旋转
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.centerIn: parent;
width: 200;
height: 200;
system: particleSystem;
emitRate: 10;
lifeSpan: 2000;
lifeSpanVariation: 500;
size: 16;
endSize: 32;
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
}
}
}
- 将每个粒子顺时针旋转15°,另外有一个5°的误差范围;
- 将这些粒子继续以每秒45°的速度旋转,也会有一个15°的误差范围;
5、用ImageParticle渲染粒子,并设置粒子效果
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.centerIn: parent;
width: 200;
height: 200;
system: particleSystem;
emitRate: 10;
lifeSpan: 2000;
lifeSpanVariation: 500;
size: 16;
endSize: 32;
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
}
}
- 我们可以修改粒子进入场景的效果,当粒子生命周期开始时,就会应用这个效果;
- 使用
entryEffect: ImageParticle.Scale
添加了一个缩放效果;
七、粒子方向
我们还可以设置粒子轨迹的方向,轨迹取决于一个指定的向量空间,该向量定义了粒子的速度和加速度,以及一个随机的方向。
QML提供了三种不同的向量空间,用于定义粒子的速度和加速度:
- 点方向(PointDirection):使用x和y值定义的方向;
- 角度方向(AngleDirection):使用角度定义方向;
- 目标方向(TargetDirection):使用一个目标点坐标定义方向;
7.1、PointDirection
PointDirection
使用x、y值导出向量空间。例如,你想让粒子轨迹沿着45°角方向,那么就要将x、y值设置成相同的值。
例如:我们希望粒子轨迹从左向右,形成一个15°的角,为了设置粒子轨迹,我们首先需要赋值PointDirection赋值给Emitter的velocity属性;
velocity: PointDirection{};
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: PointDirection {
x: 100;
y: 0;
xVariation: 0;
yVariation: 100/6;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
}
}
- 设定方向,坐标(100,0),xVariation和yVariation为误差精度;
7.2、AngleDirection
要使用AngleDirection
,我们需要将其赋值给Emitter
的velocity
属性:
velocity: AngleDirection{};
粒子发射角度使用angle
属性定义,angle
属性的取值范围是[0,360],0位水平向右。
我们希望粒子水平向右发射,因此,angle: 0;
粒子速度由magnitude
属性决定,magnitude
属性单位是像素/秒。如果我们的场景宽度是640px,那么将magnitude
属性设置为100的话,这就意味着,粒子平均要消耗6.4秒才能从场景一端移动到另一端。为了让粒子速度更有趣,我们还要设置magnitudeVariation
属性,这会为该速度设置一个可变的范围区间;
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: AngleDirection {
angle: 0;
angleVariation: 15;
magnitude: 100;
magnitudeVariation: 50;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
}
}
接下来看加速度,加速度为每一个粒子添加一个加速度向量,该向量会随着时间流逝而改变速度。
例如,我们创建一个类似星轨的轨迹,为了达到这一目的,我们将方向修改为-45°,并且移除速度变量区间:
velocity: AngleDirection {
angle: -45;
magnitude: 100;
}
加速度方向为90°向下,数值为25:
acceleration: AngleDirection {
angle: 90;
magnitude: 25
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: AngleDirection {
angle: -45;
magnitude: 100;
}
acceleration: AngleDirection {
angle: 90;
magnitude: 25;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
}
}
7.3、TargetDirection
TargetDirection
使用某个项目指定一个目标点,targetItem
指定目标位置关联Item,Item的中心会成为目标点
首先我们在界面右侧中心设置一个目标点:
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
我们将TargetDirection
的targetItem属性设置为targetPoint,targetVariation的值为100/6,这大约会形成一个15°的角;
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
}
}
八、粒子控制
粒子由发射器发射,一旦粒子发射出来,发射器的任务也就完成了,不会再对粒子有任何影响。如果我们需要控制已发射的粒子,需要使用粒子控制器(Affector
);
Affector属性介绍:
属性 | 类型 | 描述 |
---|---|---|
acceleration | StochasticDirection | 受影响的粒子将其加速度设置这个方向 |
enabled | bool | 如果设置为false,此影响器不会影响任何粒子,默认值为true |
groups | list<string> | 哪些逻辑粒子组将受到影响。如果为空,它将影响所有粒子 |
once | bool | 如果once被设置为true,这个影响器将只影响每个粒子一次。如果影响器通常模拟一段时间内的连续效应,那么它将模拟一秒时间内的效应即它影响粒子的瞬间。默认为false |
position | StochasticDirection | 受影响的粒子将其位置设置为这个方向,相对于粒子系统。当将方向解释为点时,可以将其想象为一个箭头,其基础在ParticleSystem的0,0处,尖端在指定位置处。 |
relative | bool | 受影响的粒子是否将其现有的位置/速度/加速度添加到新粒子上。默认值为true。 |
shape | Shape | 如果已定义大小,则形状属性可用于影响非矩形区域 |
system | ParticleSystem | 这就是受元件影响的系统。如果Affector是一个粒子系统的直接子元素,它将自动与粒子系统相关联。 |
velocity | StochasticDirection | 受影响的粒子将其速度设置为这个方向 |
whenCollidingWith | list<string> | 如果这里指定了任何逻辑粒子组,那么只有当被选中的粒子与这些组中的一个粒子相交时,才会触发影响器。这与groups属性不同。groups属性选择哪些粒子可以被检查,如果它们满足其他标准(包括在Affector的范围内,通过形状修改),那么它们将再次被测试,以查看它们是否与whenCollidingWith中的一个粒子组中的粒子相交。默认情况下,不指定任何组 |
Affector影响器有一个基础类型Affector,下面有八个子类型:
控制器 | 说明 |
---|---|
Age | 改变粒子生命周期,一般用于提前结束粒子的生命周期 |
Attractor | 将粒子吸引到一个指定的点 |
Friction | 按比例降低粒子的当前速率 |
Gravity | 添加一个一定角度的加速度 |
Turbulence | 为粒子添加一个图像噪音 |
Wander | 随机改变粒子轨迹 |
GroupGoal | 改变粒子组状态 |
SpriteGoal | 改变精灵粒子状态 |
8.1、Age
Age
可以改变粒子生命周期,lifeLeft
属性指定粒子还能存活多少时间。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 5000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Age {
anchors.centerIn: parent;
width: 140;
height: 120;
system: particleSystem;
advancePosition: true;
lifeLeft: 2500;
once: true;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 添加的居中绿色矩形区域为Age控制器的区域范围;
- 发射器设置的粒子生命周期为5000,Age控制器的生命周期为2500,也就是说,当粒子进入Age控制器区域后,生命周期就剩下2500了;
- advancePosition设置为true,粒子就会从其预期的位置从新出现(参考剩余生命周期、粒子速度和到目标点的距离来推算预期的位置);
8.2、Attractor
Attractor
将粒子吸引到pointX和pointY指定的点,strength
属性指定吸引的强度;
强度为1.0
强度为100.0
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 10000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Attractor {
anchors.centerIn: parent;
width: 160;
height: 70;
system: particleSystem;
pointX: 0;
pointY: 0;
strength: 100.0
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 我们的控制器位于界面中间,当粒子进入控制器范围时,控制器会影响粒子向(0,0)点方向移动;
8.3、Friction
Friction
会按一定比例降低粒子速度
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 10000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Friction {
anchors.centerIn: parent;
width: 160;
height: 70;
system: particleSystem;
factor: 0.8;
threshold: 25;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 粒子进入控制器范围后,会以factor系数为0.8的比例降低粒子速度,直到降低到threshold: 25px/s;
8.4、Gravity
Gravity
位粒子添加一个加速度;
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 10000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Gravity {
anchors.centerIn: parent;
width: 160;
height: 70;
system: particleSystem;
magnitude: 50;
angle: 90;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 进入控制器范围的粒子都会被添加一个大小为50,方向为向下90°的加速度;
8.5、Turbulence
Turbulence
为粒子添加一个力向量,每个粒子获得的力向量都是随机的,这是由一个噪音图像决定的,使用noiseSource
可以自定义噪音图像,strength
定义了力向量强度;
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 10000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Turbulence {
anchors.centerIn: parent;
width: 160;
height: 70;
system: particleSystem;
strength: 100;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 粒子一旦进入控制器范围,就会发疯一样乱窜,而不是安装从左到右的方向保持一个大致轨迹;
8.6、Wander
Wander
控制轨迹,affectedParameter
属性指定控制哪一属性(速度/位置/加速度),pace
属性指定每秒该属性变化的最大值,xVariance和yVariance指定粒子轨迹x和y坐标的浮动区间。
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 10000;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
Wander {
anchors.centerIn: parent;
width: 160;
height: 70;
system: particleSystem;
affectedParameter: Wander.Position;
pace: 200;
yVariance: 240;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 控制器作用于粒子轨迹的位置属性,轨迹以每秒200次的频率在y轴方向上随机振动;
8.7、GroupGoal
8.8、SpriteGoal
九、粒子组-ParticleGroup
每一个粒子都是粒子组(ParticleGroup
)的成员,通过其name属性区分,当没有指定粒子所属的粒子组时,这些粒子默认也都在一个粒子组,不过name
属性值是个空字符串,粒子组主要是为了方便控制粒子行为状态;
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Particles 2.0
Window {
id: root;
width: 400;
height: 400;
visible: true;
Rectangle {
id: rootItem;
width: 400;
height: 400;
color: "#1f1f1f";
ParticleSystem {
id: particleSystem;
}
Rectangle {
id: targetPoint;
anchors.right: parent.right;
anchors.verticalCenter: parent.verticalCenter;
width: 10;
height: 10;
radius: 10;
color: "red";
}
Emitter {
id: emitter;
anchors.left: parent.left;
anchors.verticalCenter: parent.verticalCenter;
group: "A";
width: 1;
height: 1;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 32;
velocity: TargetDirection {
targetItem: targetPoint;
targetVariation: 100/6;
magnitude: 100;
}
}
Emitter {
id: emitter2;
anchors.left: parent.left;
anchors.bottom: parent.bottom;
anchors.bottomMargin: 20;
group: "B";
width: 10;
height: 10;
system: particleSystem;
emitRate: 10;
lifeSpan: 6400;
lifeSpanVariation: 400;
size: 10;
velocity: AngleDirection {
angle: 0;
magnitude: 100;
}
}
ImageParticle {
system: particleSystem;
groups: "A";
source: "qrc:/Sources/assets/star.png";
color: "#FFD700";
colorVariation: 0.6;
rotation: 15;
rotationVariation: 5;
rotationVelocity: 45;
rotationVelocityVariation: 15;
entryEffect: ImageParticle.Scale;
}
ItemParticle {
system: particleSystem;
groups: "B";
delegate: Rectangle {
color: "green";
width: 10;
height: 10;
radius: 10;
}
}
Wander {
anchors.centerIn: parent;
width: 160;
height: parent.height;
system: particleSystem;
groups: ["A","B"];
affectedParameter: Wander.Position;
pace: 500;
yVariance: 400;
Rectangle {
anchors.fill: parent;
color: "transparent";
border.color: "green";
border.width: 2;
}
}
}
}
- 定义了两个粒子发射器,分别是groupA和groupB;
- groupA使用的是ImageParticle画刷,groupB使用的是ItemParticle画刷;
- 两个组同时使用Wander控制器;
十、烟花案例
转载自:【使用Qt Quick Particle System粒子系统实现烟花效果】
https://blog.csdn.net/yafeilinux/article/details/86530616
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Particles 2.12
import QtMultimedia 5.9
Window {
visible: true;
width: 800;
height: 530;
color: "black";
title: qsTr("Hello World");
//声音
SoundEffect {
id:playSound;
source: "qrc:/sound.wav";
}
//背景
Image {
anchors.fill: parent;
source: "qrc:/back.jpg";
}
//粒子系统
ParticleSystem {
id: particles;
anchors.fill: parent;
//-----------------------------------------------------------------
//发射出去的粒子画笔
ImageParticle {
groups: ["stage1"]; //分组为stage1
source: "qrc:///particleresources/star.png"; //这是QML内置的一个路径,能够在源代码包内搜索particlesources这个目录
alphaVariation: 0.4; //透明度误差
colorVariation: 0.9; //颜色误差
}
//发射出去的粒子发射器
Emitter {
id: burstEmitter;
x: 400;
y: 480;
group: "stage1"; //分组为stage1
emitRate: 3; //发射速率为1秒5个
lifeSpan: 1500; //粒子生命周期为1500ms
size: 50; //粒子大小为50px
endSize: 10; //粒子消亡时大小为10px
sizeVariation: 30; //粒子大小误差
acceleration: PointDirection { //粒子加速度
y: 100;
}
velocity: AngleDirection { //粒子速率
angle: 270; //粒子发射角度
magnitude: 400; //粒子速率为400像素/秒
angleVariation: 40; //角度误差
magnitudeVariation: 50; //速率误差
}
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//发射出去的粒子后面烟气效果粒子画笔
ImageParticle {
groups: ["stage2"]; //分组为stage2
source: "qrc:///particleresources/glowdot.png"; //这是QML内置的一个路径,能够在源代码包内搜索particlesources这个目录
color: "#11111111"; //粒子颜色
}
//发射出去的粒子后面烟气效果粒子发射器
TrailEmitter {
group: "stage2"; //分组为stage2
follow: "stage1"; //跟随stage1
emitRatePerParticle: 100;
lifeSpan: 2400; //粒子生命周期为2400ms
lifeSpanVariation: 400; //粒子生命周期误差
size: 16; //粒子大小
endSize: 0; //粒子生命周期结束时大小
sizeVariation: 8; //粒子大小误差
acceleration: PointDirection { //粒子加速度
y: -60;
}
velocity: AngleDirection { //粒子速率
angle: 270; //粒子发射角度
magnitude: 40; //粒子速率为40像素/秒
angleVariation: 22; //角度误差
magnitudeVariation: 5; //速率误差
}
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//爆炸的粒子画笔
ImageParticle {
id: imageParticle;
groups: ["stage3"]; //分组为stage3
source: "qrc:///particleresources/star.png"; //这是QML内置的一个路径,能够在源代码包内搜索particlesources这个目录
alpha: 0;
colorVariation: 0.2; //颜色误差
entryEffect: ImageParticle.Scale; //粒子效果为放缩
rotation: 60; //旋转角度
rotationVariation: 30; //旋转角度误差
rotationVelocity: 45; //旋转速率
rotationVelocityVariation: 15; //旋转速率误差
}
//爆炸的粒子发射器
Emitter {
id: burstEmitter2;
group: "stage3"; //分组为stage3
emitRate: 4000; //发射速率为4000个每秒
lifeSpan: 3000; //生命周期为3000ms
size: 30; //粒子大小
endSize: 5; //粒子生命周期结束时大小
sizeVariation:10; //粒子大小误差
enabled: false; //发射器不起作用
velocity: CumulativeDirection { //粒子速率,CumulativeDirection将多个方向合一
AngleDirection {
angleVariation: 360;
magnitudeVariation: 80;
}
PointDirection {
y: 20;
}
}
acceleration: PointDirection { //粒子加速度
y: 10;
}
}
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//粒子控制器
Affector {
system: particles
width: parent.width
height: 10;
y: 90;
once: true; //只影响粒子一次
groups: "stage1"; //影响分组stage1的粒子
onAffectParticles: {
for (var i=0; i<particles.length; i++) {
burstEmitter2.burst(500, particles[i].x, particles[i].y); //Emitter::burst(int count, int x, int y)会在(x,y)出瞬间发射出count个粒子
imageParticle.color = Qt.rgba(particles[i].red, //设置爆炸粒子画笔的颜色
particles[i].green,
particles[i].blue,
particles[i].alpha)
playSound.play(); //播放声音
}
}
// Rectangle {
// anchors.fill: parent;
// color: "transparent";
// border.color: "green";
// border.width: 2;
// }
}
}
}