粒子系统能够单独每个元素设置生命周期,颜色,大小,运动轨迹等特点。所以能够模拟火焰,烟雾,天气等特效。
用sfml写了个简单的粒子系统
#include <SFML/Graphics.hpp>
#include <vector>
#include <random>
#define PARTICLE_NUMBER 1000
typedef struct Particle
{
sf::Vector2i Pos;
sf::Color Color;
float LivedTime;
float MaxLiveTime;
bool IsAlive;
}Particle;
std::vector<Particle> g_particlesVector;//粒子容器
sf::Vector2i g_sourcePoint;//发射点
//随机数产生器
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> posDist(-20, 10); // 粒子的初始位置范围
std::uniform_real_distribution<float> liveDist(1.0, 3.0); // 粒子的生命范围
std::uniform_int_distribution<int> posOffsetDist(-5, 5); // 粒子的偏移范围
sf::Clock g_updateClock;
void generate_particles(){
Particle p;
p.Pos.x = g_sourcePoint.x+posDist(gen);
p.Pos.y = g_sourcePoint.y+posDist(gen);
p.Color = sf::Color(255,255,255,255);
p.MaxLiveTime = liveDist(gen);
p.LivedTime = 0;
p.IsAlive = true;
g_particlesVector.push_back(p);
}
void generate_particles_to_vector(){
if(g_particlesVector.size()>=PARTICLE_NUMBER){
return;
}
for(unsigned int i=0;i<PARTICLE_NUMBER-g_particlesVector.size();i++){
generate_particles();
}
}
void update_particle(Particle &p,float time){
p.Pos.y -= 5;
p.Pos.x += posOffsetDist(gen);
p.LivedTime += time;
if(p.LivedTime>=p.MaxLiveTime){
p.IsAlive = false;
}else{
//更新颜色
p.Color.r>8?p.Color.r -= 8:p.Color.r=0;
p.Color.b>8?p.Color.b -= 8:p.Color.b=0;
}
}
void update_particles_vector(){
float time = g_updateClock.getElapsedTime().asSeconds();
if(time<0.04){
return;
}
for(std::vector<Particle>::iterator it = g_particlesVector.begin();it != g_particlesVector.end();){
update_particle(*it,time);
if(it->IsAlive){
it++;
}else{
it = g_particlesVector.erase(it);
}
}
g_updateClock.restart();
}
int main()
{
sf::RenderWindow window(sf::VideoMode(400, 400), "Particle System");
window.setFramerateLimit(30);
g_sourcePoint.x = 200;
g_sourcePoint.y = 300;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
//绘制粒子
sf::VertexArray point(sf::Points);
for(auto &any:g_particlesVector){
point.append(sf::Vertex(sf::Vector2f(any.Pos), any.Color));
}
window.draw(point);
window.display();
//产生和更新粒子
generate_particles_to_vector();
update_particles_vector();
}
return 0;
}
这些粒子是像素点,也可以使用某些纹理图片呈现更真实的效果。