SFML粒子系统

⌚Time: 2024-09-12 16:53:00

👨‍💻Author: Jack Ge

粒子系统能够单独每个元素设置生命周期,颜色,大小,运动轨迹等特点。所以能够模拟火焰,烟雾,天气等特效。

用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;
}

这些粒子是像素点,也可以使用某些纹理图片呈现更真实的效果。