Введение
Системы частиц — способ создать визуально насыщенные эффекты (искры, дождь, дым, конфетти при успешном действии) из большого количества простых, однотипных элементов, движущихся по заданным правилам. Qt Quick предоставляет встроенный модуль QtQuick.Particles для декларативного описания таких эффектов прямо в QML, без необходимости вручную анимировать каждый отдельный элемент. В статье разберём базовую структуру системы частиц.
Концепция
Система частиц в Qt Quick состоит из нескольких связанных компонентов: ParticleSystem — корневой контейнер, координирующий все остальные части; ImageParticle или ItemParticle — определяет, как выглядит каждая отдельная частица (изображение или произвольный QML-компонент); Emitter — определяет, где, как часто и с какими начальными параметрами (скорость, направление, время жизни) рождаются новые частицы; и опционально различные «воздействия» (Gravity, Wander, Turbulence) — модификаторы, влияющие на движение частиц после их рождения.
Пример кода: Qt Quick Particles
import QtQuick
import QtQuick.Particles
Item {
width: 400
height: 400
ParticleSystem {
id: particleSystem
}
// Определяет визуальное представление частиц — здесь простое изображение искры
ImageParticle {
system: particleSystem
source: "qrc:/particles/spark.png"
color: "#ffaa33"
colorVariation: 0.3 // случайная вариация оттенка для каждой частицы
alpha: 0.8
}
// Источник рождения частиц — расположен в центре сцены
Emitter {
id: emitter
system: particleSystem
anchors.centerIn: parent
emitRate: 50 // частиц в секунду
lifeSpan: 2000 // время жизни каждой частицы в миллисекундах
lifeSpanVariation: 500
size: 16
sizeVariation: 8
velocity: AngleDirection {
angle: 270 // направление "вверх" (270 градусов в системе координат Qt Quick)
angleVariation: 45 // случайное отклонение направления для естественности эффекта
magnitude: 100
magnitudeVariation: 50
}
enabled: false // по умолчанию выключен, активируется программно
}
// Гравитация, постепенно "роняющая" частицы вниз — типична для эффекта искр/конфетти
Gravity {
system: particleSystem
magnitude: 150
angle: 90
}
MouseArea {
anchors.fill: parent
onClicked: {
emitter.enabled = true;
burstTimer.start();
}
}
Timer {
id: burstTimer
interval: 300
onTriggered: emitter.enabled = false // короткий "всплеск" частиц при клике
}
}
Пояснения к коду
ParticleSystem сам по себе не имеет визуального представления — это координирующий объект, к которому через свойство system подключаются все остальные части (ImageParticle, Emitter, Gravity). ImageParticle определяет, что каждая отдельная частица — это изображение spark.png с заданным базовым цветом и случайной вариацией оттенка (colorVariation), что делает множество одновременно видимых частиц визуально разнообразнее, а не идентичными копиями друг друга.
Emitter настраивает параметры рождения частиц — emitRate определяет интенсивность эффекта, velocity через AngleDirection задаёт направление и силу начального «импульса» каждой частицы с элементом случайности (angleVariation, magnitudeVariation) для естественного, не механически одинакового вида эффекта. Gravity — пример воздействия, постоянно влияющего на все частицы системы после их рождения, создавая эффект падения под действием «силы тяжести», направленной в данном случае вниз (угол 90 градусов). Включение emitter.enabled по клику и таймер, выключающий его через короткое время, создают эффект кратковременного «всплеска» частиц, а не непрерывного потока.
Подводные камни
- Большое количество одновременно видимых частиц (высокий
emitRateв сочетании с длительнымlifeSpan) может создавать значительную нагрузку на рендеринг, особенно на слабом оборудовании или embedded-устройствах (основной цикл статей, статья 242) — количество одновременно живых частиц равно приблизительноemitRate × lifeSpan / 1000, и для эффекта сemitRate: 50иlifeSpan: 2000это около 100 одновременных частиц, что для большинства устройств приемлемо, но для более интенсивных эффектов стоит явно тестировать производительность на целевом железе. - Угол в
AngleDirectionотсчитывается не интуитивно для разработчиков, ожидающих стандартную математическую систему координат — в Qt Quick ось Y направлена вниз, и угол 270 градусов соответствует направлению «вверх» на экране, а не привычному из математики направлению вправо при угле 0 — путаница с направлением углов частая причина, когда частицы «летят не туда, куда ожидалось» при первой попытке настройки эмиттера. - Файл изображения частицы, заданный с неверным путём или не включённый в Qt Resource System, тихо не создаёт видимого эффекта — частицы продолжают логически существовать и двигаться согласно настройкам, но визуально невидимы, что легко спутать с проблемой настройки самого эмиттера, тогда как реальная причина — простая опечатка в пути к ресурсу изображения.
- Время жизни приложения с активной, но не остановленной системой частиц (забытый
emitter.enabled = falseили работающий бесконечноTimer) продолжает потреблять ресурсы на генерацию и анимацию частиц даже когда визуальный эффект давно не нужен пользователю — для эффектов, призванных быть кратковременными (как взрыв конфетти при успешном действии), важно явно и надёжно останавливать эмиттер после завершения нужной продолжительности эффекта.