一、粒子往哪里飞

上一篇解决了"粒子从哪里出生"的问题,这一篇解决"粒子往哪里飞"。粒子的运动方向由 Emitter 的 velocity(速度)和 acceleration(加速度)属性控制,两者的值类型都是 Direction(实际为 StochasticDirection)。

Qt Quick 粒子系统提供了三种基础 Direction 模型和一种组合模型:AngleDirection(极坐标模型)、PointDirection(直角坐标模型)、TargetDirection(目标点模型)、CumulativeDirection(组合模型)。每种模型对应不同的参数输入方式,选错模型会导致参数难以理解或效果不符合预期。

本文围绕"你有什么参数就用什么模型"展开,先讲数学本质,再通过五个示例演示参数调优。


二、开发环境与版本说明

本文所有代码基于以下环境验证(验证日期:2026-06-10):

  • Qt 版本:6.8.2
  • 编译器:MinGW 64-bit
  • 操作系统:Windows 11
  • 构建工具:CMake 3.29

Direction 的 API 从 Qt 5 起稳定,Qt 6.5+ 均可直接运行本文代码。


三、原理分析:三种方向模型

3.1 Direction 的角色

Direction 是 Emitter 的 velocityacceleration 属性的值类型(实际类型为 StochasticDirection,Direction 是其基类)。它定义了一个速度向量加速度向量

  • velocity:粒子诞生时的初始速度,决定粒子往哪飞、飞多快
  • acceleration:粒子受到的持续加速度,决定粒子的运动轨迹如何变化

一个粒子的运动可以用物理公式描述:

位置 = 初始位置 + velocity × t + 0.5 × acceleration × t²

两者可以使用不同的 Direction 模型。

3.2 AngleDirection:极坐标模型

输入参数:角度(angle)+ 速度大小(magnitude)

数学本质:将速度分解为直角坐标分量

vx = magnitude × cos(angle)
vy = magnitude × sin(angle)

关键属性

属性 含义 默认值
angle 发射角度(度) 0
angleVariation 角度随机偏移范围 0
magnitude 速度大小(像素/秒) 0
magnitudeVariation 速度大小随机偏移范围 0

角度参考系:Qt Quick 的角度以向右为 0 度,顺时针递增:

角度参考系

0° → 向右

90° → 向下

180° → 向左

270° → 向上

适用场景:均匀扩散、锥形喷射、定向发射。当你知道"往哪个角度飞、飞多快"时,用 AngleDirection。

3.3 PointDirection:直角坐标模型

输入参数:x 方向速度 + y 方向速度

数学本质:直接指定速度的 x/y 分量,不做坐标转换

vx = x + random(-xVariation, +xVariation)
vy = y + random(-yVariation, +yVariation)

关键属性

属性 含义 默认值
x x 方向速度分量 0
xVariation x 方向随机偏移 0
y y 方向速度分量 0
yVariation y 方向随机偏移 0

适用场景:抛物线轨迹(配合 acceleration)、定向流动、锥形扩散。当你知道"x 方向飞多快、y 方向飞多快"时,用 PointDirection。

3.4 TargetDirection:目标点模型

输入参数:目标点坐标(targetX, targetY)+ 速度大小(magnitude)

数学本质:速度方向指向目标点,大小由 magnitude 决定

dx = targetX - particle.x
dy = targetY - particle.y
angle = atan2(dy, dx)
vx = magnitude × cos(angle)
vy = magnitude × sin(angle)

关键属性

属性 含义 默认值
targetX 目标点 x 坐标(相对于 Emitter) 0
targetY 目标点 y 坐标(相对于 Emitter) 0
targetItem 目标 Item(优先级高于 targetX/targetY)
targetVariation 目标点随机偏移范围 0
magnitude 速度大小(像素/秒) 0
magnitudeVariation 速度大小随机偏移 0
proportionalMagnitude 是否按距离比例计算速度 false

targetItem:可以直接绑定一个 QML Item 作为目标,优先级高于 targetX/targetY。无需手动计算坐标偏移。

proportionalMagnitude:设为 true 时,magnitude 被解释为"距目标点距离的倍数/秒"——粒子离目标远时速度快,接近时自动减速,产生自然的减速效果。默认 false,magnitude 为固定像素/秒。

适用场景:粒子汇聚、吸引效果、指向性发射。当你知道"飞向哪个点"时,用 TargetDirection。

3.5 CumulativeDirection:组合模型

数学本质:多个 Direction 的速度向量叠加

v_total = v_1 + v_2 + ... + v_n

CumulativeDirection 内部可以包含任意数量的子 Direction,它们的速度向量会相加。比如一个 AngleDirection(随机扩散)叠加一个 PointDirection(定向偏移),粒子就同时具有扩散和定向运动。

适用场景:需要同时具有多种运动特征的复合效果。

3.6 选型决策

角度 + 速度大小

X/Y 速度分量

目标点坐标

多种方向叠加

你有什么参数?

AngleDirection
极坐标模型

PointDirection
直角坐标模型

TargetDirection
目标点模型

CumulativeDirection
组合模型

均匀扩散、锥形喷射

抛物线、定向流动

粒子汇聚、吸引效果

扩散+定向复合运动

3.7 velocity 与 acceleration 的配合

两者的常见搭配模式:

  • 纯 velocity:粒子匀速直线运动
  • velocity + acceleration:粒子变速运动(如抛物线)
  • 纯 acceleration(velocity 为 0):粒子从静止开始加速

最经典的配合是"抛物线":velocity 用 AngleDirection(斜向上),acceleration 用 PointDirection(向下重力)。


四、代码实现

4.1 Direction_AngleSpread.qml:水平扩散

每个示例都由 ParticleSystemImageParticleEmitter 三部分组成,后续只展示 Emitter 核心配置。

Emitter {
    anchors.left: parent.left
    anchors.verticalCenter: parent.verticalCenter
    width: 1; height: 1
    emitRate: 100
    lifeSpan: 4000
    size: 10
    velocity: AngleDirection {
        angle: 0                // 基础方向向右
        angleVariation: 30      // ±30° 随机偏移
        magnitude: 150          // 速度 150 像素/秒
        magnitudeVariation: 50  // 速度在 [100, 200] 之间随机
    }
}

结果是粒子从左侧向右呈扇形扩散,扩散角度 60 度(±30 度)。magnitudeVariation双向偏移(150 ± 50),速度不同的粒子形成参差不齐的前沿。

4.2 Direction_Parabolic.qml:抛物线轨迹

Emitter {
    anchors.left: parent.left
    anchors.verticalCenter: parent.verticalCenter
    width: 1; height: 1
    emitRate: 60
    lifeSpan: 4000
    size: 10
    velocity: AngleDirection {
        angle: 315
        angleVariation: 10
        magnitude: 200
        magnitudeVariation: 30
    }
    acceleration: PointDirection {
        y: 80
    }
}

velocityangle: 315 表示向右上方发射。推导过程:0° 是正右方,90° 是正下方(顺时针递增),270° 是正上方,所以 315° = 270° + 45° = 向上偏右 45°。magnitude: 200 表示初始速度较快。

accelerationPointDirection { y: 80 } 表示持续向下的加速度,模拟重力。注意 y: 80 是正值——在 Qt Quick 坐标系中,y 轴向下为正,所以正值 y 表示向下的加速度。

两者配合产生了抛物线轨迹:粒子先斜向上飞,速度逐渐被重力抵消,到达最高点后开始下落。

4.3 Direction_ConeSpread.qml:锥形扩散

Emitter {
    x: parent.width / 2
    y: 80
    width: 1; height: 1
    emitRate: 100
    lifeSpan: 3000
    size: 10
    velocity: PointDirection {
        x: 0
        y: 150
        xVariation: 60
        yVariation: 30
    }
}

x: 0, y: 150 表示基础方向向下,xVariation: 60 表示水平方向 ±60 的随机偏移,yVariation: 30 表示垂直方向 ±30 的随机偏移。结果是粒子从顶部向下呈锥形扩散——中心区域粒子密集,边缘稀疏。

这个效果用 AngleDirection 也能实现(angle: 90, angleVariation: 20),但 PointDirection 更直观地表达了"向下为主、左右偏移"的意图。

4.4 Direction_TargetSpread.qml:目标扩散

Emitter {
    anchors.left: parent.left
    anchors.verticalCenter: parent.verticalCenter
    width: 1; height: 1
    emitRate: 80
    lifeSpan: 4000
    size: 10
    velocity: TargetDirection {
        targetX: targetPoint.x - emitter.x
        targetY: targetPoint.y - emitter.y
        targetVariation: 80
        magnitude: 120
        magnitudeVariation: 30
    }
}

targetX / targetY:目标点坐标是相对于 Emitter 的偏移量。代码中用 targetPoint.x - emitter.xtargetPoint.y - emitter.y 通过 QML 属性绑定动态计算——当目标点或 Emitter 移动时,偏移量会自动更新,粒子始终指向目标点。

实际上 TargetDirection 还提供了 targetItem 属性,可以直接绑定目标 Item,不需要手动计算偏移:targetItem: targetPoint。本例使用手动计算是为了演示相对坐标的含义。

targetVariation: 80:目标点的随机偏移范围。设为 80 意味着粒子不会精确飞向目标点,而是在目标点周围 80 像素的范围内随机偏移,避免"激光"效果。目标点用一个带呼吸动画的绿色圆形标记。

4.5 Direction_Cumulative.qml:组合方向

Emitter {
    anchors.centerIn: parent
    width: 1; height: 1
    emitRate: 100
    lifeSpan: 4000
    size: 10
    velocity: CumulativeDirection {
        AngleDirection {
            angle: 0
            angleVariation: 360
            magnitude: 80
        }
        PointDirection {
            x: 50
            y: 0
        }
    }
}

CumulativeDirection 包含两个子 Direction,速度向量逐帧相加

  • AngleDirectionangleVariation: 360 全方向随机扩散,提供均匀的"圆"
  • PointDirectionx: 50 向右偏移,提供一个向右的"箭头"

叠加后,向右的粒子更快,向左的粒子更慢甚至反向——整体呈现"被风吹动的烟花"效果。

4.6 同一个效果,不同实现——模型对比

以"锥形扩散"(粒子从顶部向下发射,水平随机偏移)为例,两种模型都能实现:

// 方案 A:AngleDirection —— 用角度控制扩散范围
velocity: AngleDirection {
    angle: 90; angleVariation: 20; magnitude: 150
}

// 方案 B:PointDirection —— 用 X/Y 分量控制偏移范围
velocity: PointDirection {
    x: 0; y: 150; xVariation: 60; yVariation: 30
}

两者的视觉效果接近,但参数直觉不同:AngleDirection 的 angleVariation 控制扇形张角,适合喷射、火焰;PointDirection 的 xVariation 控制左右散布范围,适合雨帘、瀑布。选型依据:角度是核心参数用 AngleDirection,水平/垂直偏移量是核心参数用 PointDirection。

4.7 参数调优指南

模型 想要效果 调整什么
AngleDirection 扩散更集中/更宽 减小/增大 angleVariation(0~360)
AngleDirection 粒子飞得更远 增大 magnitude
PointDirection 左右散布更宽 增大 xVariation
PointDirection 上下散布更宽 增大 yVariation
抛物线 更陡峭 增大 acceleration.y
抛物线 飞得更高 增大 velocity.magnitude

规律:Variation 控制随机范围,基础值控制主运动方向和强度


五、运行效果

Direction_AngleSpread.qml:红色星形粒子从页面左侧向右呈扇形扩散,扩散角度约 60 度。
在这里插入图片描述

Direction_Parabolic.qml:青色星形粒子从左侧斜向上发射,在重力作用下画出优美的抛物线轨迹。
在这里插入图片描述

Direction_ConeSpread.qml:黄色星形粒子从顶部向下呈锥形扩散,中心密集、边缘稀疏。
在这里插入图片描述

Direction_TargetSpread.qml:绿色星形粒子从左侧向右上方的目标点汇聚,但不精确——带有自然的发散效果。目标点有呼吸动画标记。
在这里插入图片描述

Direction_Cumulative.qml:青色星形粒子从中心向四面八方扩散,但整体有明显的向右漂移趋势。
在这里插入图片描述


六、适用边界与限制条件

  • velocity 只能设一个 Direction,不能同时写两个。需要多种方向叠加时用 CumulativeDirection,但 velocityacceleration 可以使用不同的模型
  • acceleration 最常用 PointDirection(如重力 y: 80),AngleDirection 和 TargetDirection 作为加速度时语义不直观
  • 角度单位是度(0-360),向右为 0 度,顺时针递增:0° = 右,90° = 下,270° = 上
  • TargetDirection 的 targetX/targetY 是相对坐标(相对于 Emitter)。不想手动计算可以用 targetItem 直接绑定目标 Item
  • magnitude 为 0 时粒子静止,有 acceleration 则从静止开始加速
  • angleVariation 为 0 时所有粒子精确沿 angle 方向发射;为 360 时完全随机扩散

七、总结

回到开头的问题:“粒子往哪里飞?”——答案取决于你手里的参数。

三种模型的核心区别在于参数输入方式:AngleDirection 用极坐标,PointDirection 用直角坐标,TargetDirection 用目标点坐标。同一个效果(如锥形扩散)可以用不同模型实现,选择取决于哪个模型的参数更符合你的直觉。需要多种运动叠加时,CumulativeDirection 将多个向量相加。

velocity 和 acceleration 可以混用不同模型。最经典的配合是"抛物线":velocity 用 AngleDirection 控制发射方向,acceleration 用 PointDirection 模拟重力。

下一篇讲解粒子的随机性参数——位置、速度、角度。


资源下载qml_particlesystem —— 包含完整的、可运行的代码

系列目录

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐