Простая система частиц на SFML C++
Простая система частиц на SFML C++
Приветствую всех, кто интересуется графикой и программированием! Сегодня мы погрузимся в увлекательный мир создания систем частиц с помощью библиотеки SFML на C++. Эта тема открывает широкие возможности для визуализации различных эффектов, от простых искр и дыма до сложных взрывов и магических заклинаний в играх и других приложениях.
Системы частиц — это мощный инструмент для генерации динамических визуальных эффектов. Они основаны на идее создания множества мелких объектов (частиц), каждый из которых обладает собственными параметрами, такими как положение, скорость, цвет, размер и время жизни. Управляя этими параметрами, можно добиться самых разнообразных результатов.
Создадим отдельный класс для управления системой частиц.
Назовём его ParticleSystem. Ниже реализация кода данного класса.
Опишем свойства и методы класса ParticleSystem.
Класс наследуется от классов библиотеки SFML:
Drawable - позволяет объектам класса ParticleSystem быть нарисованными с помощью метода window.draw, переопределяя метод draw;
Transformable - позволяет использовать трансформации, в нашем случае перемещение для всей системы частиц.
Публичные поля.
Конструктор класса - инициализирует систему частиц.
Метод addParticle добавляет новую частицу в систему.
Параметры данного метода:
position - начальная позиция частицы;
velocity - вектор скорости;
color - цвет частицы.
Метод update - обновляет состояние всех частиц.
Параметры метода:
elapsed - время, прошедшее с момента последнего обновления, используется для корректного перемещения частиц;
window - cсылка на графическое окно, для проверки, находятся ли частицы внутри границ окна.
Приватные поля.
Контейнер вектор particles для хранения всех частиц. Каждая частица представляет собой объект структуры Particle.
Массив вершин vertices, представляющий графическое отображение всех частиц. Связывает частицы с их визуальными атрибутами это позиция и цвет.
Виртуальный метод draw. Это переопределённый метод от класса Drawable, отвечающий за отрисовку частиц.
Далее реализовываем методы данного класса.
Конструктор ParticleSystem устанавливает тип графического примитива массива вершин как "точки". Это значит, что каждая вершина будет отрисовываться как отдельная точка на экране.
Метод добавления частицы addParticle. Добавляет новую частицу в систему. Создаёт объект Particle, в который записываются: позиция, скорость, цвет. Этот объект добавляется в массив particles т.е. вектор всех частиц. Создаётся вершина vertex, которая определяет: позицию частицы и цвет частицы. Эта вершина добавляется в массив vertices, чтобы позже её можно было отобразить.
Метод обновления частиц update. Обновляет позиции частиц и удаляет те частицы, которые вышли за границы окна. Создаются временные контейнеры:
updatedParticles - для хранения обновлённых частиц;
updatedVertices - для хранения новых вершин, соответствующих обновлённым частицам.
Цикл перебирает каждую частицу из вектора particles. Вычисляется новое положение частицы. Если новая позиция частицы находится в пределах границ окна: Частица добавляется в updatedParticles. Создаётся соответствующая вершина, которая добавляется в updatedVertices. После завершения цикла, cтарые массивы particles и vertices заменяются на новые с использованием move для оптимального переноса данных.
Метод отрисовки draw отвечает за отрисовку системы частиц на экране. Метод является переопределением функции draw из класса Drawable. Конструкция states.transform *= getTransform() применяет текущую трансформацию, например позицию к нашей точке, перед отрисовкой. Далее target.draw(vertices, states) отрисовывает массив вершин vertices на целевом объекте target т.е. RenderWindow.
В следующем коде используем данный класс для реализации эффекта фейерверка т.е. распыления частиц в разные стороны, пока будет зажата левая кнопка мыши.
Устанавливаем глобальные переменные для генерации случайных чисел.
std::random_device rd;
std::mt19937 gen(rd());
Функция randomFloat возвращает случайное число с плавающей точкой в диапазоне от min до max.
Функция randomInt возвращает целое случайное число в заданном диапазоне.
sf::RenderWindow window(sf::VideoMode(1280, 720), "Particle System with Modules");
Данный код создаёт графическое окно размером 1280 x 720 пикселей с заголовком «Particle System with Modules».
Объекты и переменные:
particles - экземпляр системы частиц, где хранятся и обновляются данные о частицах;
clock - таймер для измерения времени между кадрами т.е. управление скоростью обновления;
mousePressTimer - таймер для определения длительности удержания левой кнопки мыши;
isMousePressed - флаг, указывающий, зажата ли левая кнопка мыши; emitterPosition - позиция эмиттера т.е. координаты точки появления частиц.
Блок обработки событий:
event - объект для обработки событий;
if (event.type == sf::Event::Closed) window.close();
Конструкция обработки события закрытия окна. Если пользователь нажал кнопку "Закрыть", окно закрывается.
Блок обработки события - нажатие и удержание левой кнопки мыши.
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left) {
isMousePressed = true;
mousePressTimer.restart();
emitterPosition = sf::Vector2f(sf::Mouse::getPosition(window));
}
if (event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left) {
isMousePressed = false;
}
При нажатии кнопки мыши, устанавливается флаг isMousePressed в положение true. Сбрасывается таймер mousePressTimer т.е. запускается отсчёт времени. Записывается текущая позиция мыши в emitterPosition.
При отпускании кнопки: флаг isMousePressed сбрасывается.
Также не забываем создать глобальный цикл графического окна while (window.isOpen()) и цикл обработки событий while (window.pollEvent(event)).
Блок обновление частиц:
elapsed - время, прошедшее с последнего кадра, используется для обновления движения частиц.
if (mousePressTimer.getElapsedTime().asMilliseconds() >= 1.0f)
Если мышь зажата, каждую одну миллисекунду создаётся новая частица.
float angle = randomFloat(0.f, 360.f) * 3.14f / 180.f;
Вычисляется случайный угол и скорость частицы.
float speed = randomFloat(50.f, 200.f);
Вычисляется начальная скорость и цвет.
Новая частица добавляется в систему через метод addParticle.
Метод particlesupdate обновляет все частицы.
Далее очищаем графическое окно window.clear(), отрисовываем частицы через метод draw системы частиц window.draw(particles).
window.display()
Отображаем новый кадр.
Более подробную инструкцию вы можете получить, посмотрев видео «Простая система частиц SFML C++»
В этой статье мы разберем как сделать простой шейдер дождя и намокания поверхностей, который будет управляться внешним скриптом-контроллером. В этом простом примере мы учтем весь производственный цикл и рассмотрим как сделать все этапы правильно 🥸
Бывало ли такое, что вы вложили всю душу в создание потрясающей игры на Unity, а потом видите, как ее мучают проблемы с производительностью? Лаги и вылеты могут отпугнуть игроков. Но не пугайтесь, при правильном подходе к оптимизации памяти вы сможете добиться высокой производительности даже в самых крупных проектах.
Проект начал кодится по итогу на юнити.ДИСКЛЕЙМЕР: Платить зп у меня возможности нет в настоящий момент. Даже если вы замечательный специалист - но готовы работать только за деньги в руки - ничем не могу помочь.Теперь для оставшихся.
Ну что погнали, тема сегодняшней главы такова:
Во второй части нашей трилогии об игровом движке Nau Engine мы обсудим важные аспекты оптимизации и повышения производительности. Наша цель — выявить проблемы, которые могут повлиять на эффективность и стабильность игр, созданных с использованием Nau Engine.
Привет! Рад написать новую статью, в которой я постараюсь для обычного рядового геймера по пальцам объяснить, за что отвечают графические настройки в играх, потому что многие геймеры до сих пор не понимают, что такое антиалиасинг, вертикальная синхронизация и так далее. А эти штуки напрямую влияют на игровой процесс (вертикальная синхронизация так…
Поиски заинтересованного кодера пока идут безрезультатно. Поэтому делаю несложные скрипты при помощи чатаЖПТ. Пока получается. Сделал базовую смену дня и ночи с автоматическим включением и выключением ночных фонарей и сменой цвета глобального освещения, сделал покачивание предметов, как при левитации, сделал вращение кое-где и тд.
На сколько реально вообще запрограммировать механики прототипа при помощи нейросетей при условии, что я буду подробно ему давать описание каждого параметра и как это должно работать человеческим языком?
Решил коротко рассказать про некоторые хитрые штуковины, которые используются при разработке игр. Штуки эти общеупотребимы, поэтому используются почти во всех играх. И если вы далеки от разработки игр, то некоторые штуки, думаю, вам будет интересно узнать.
На днях вспомнил про свой пет-проект семилетней давности и подумал, что будет интересно поделиться тем, как я почти "сделал" Fallout на WPF с 20 fps-геймингом.