【问题标题】:C++ Particle System Allegro 5C++ 粒子系统 Allegro 5
【发布时间】:2013-04-23 15:44:33
【问题描述】:

我目前正在制作一个粒子系统,一个基本的,同样使用 Allegro 5 库。

这是我想出的:

int main()
{

    int mouseX = 0, mouseY = 0;
    int randNum = 0;


    std::vector <Particle *> Particles;
    bool running = false, redraw =  false, mouseHold = false;
    int particleCount = 0;

    al_init();
    al_init_image_addon();
    al_install_mouse();
    al_init_font_addon();
    al_init_ttf_addon();

    ALLEGRO_DISPLAY* display = al_create_display(800, 600);
    ALLEGRO_EVENT_QUEUE* event_queue = al_create_event_queue();
    ALLEGRO_TIMER* myTimer = al_create_timer(1.0 / 60);
    ALLEGRO_TIMER* pTimer = al_create_timer(1.0 / 120);
    ALLEGRO_FONT* myFont = al_load_ttf_font("MyFont.ttf", 20, NULL);

    al_register_event_source(event_queue, al_get_display_event_source(display));
    al_register_event_source(event_queue, al_get_timer_event_source(myTimer));
    al_register_event_source(event_queue, al_get_timer_event_source(pTimer));
    al_register_event_source(event_queue, al_get_mouse_event_source());

    running = true;
    al_start_timer(myTimer);
    while(running)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(event_queue, &ev);

        if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
            running = false;

        if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
        {
            mouseX = ev.mouse.x;
            mouseY = ev.mouse.y;
        }

        if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
        {
            if(ev.mouse.button == 1)
                mouseHold = true;
        }

        if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
        {
            if(ev.mouse.button == 1)
                mouseHold = false;
        }

        if(ev.type == ALLEGRO_EVENT_TIMER)
        {
            randNum = (std::rand()+1 * ev.timer.count) % 50;
            std::cout << randNum << std::endl;

            if(mouseHold)
            {
                Particle* particle = new Particle(mouseX + randNum, mouseY + randNum);
                Particles.push_back(particle);
            }

            particleCount = Particles.size();
            for(auto i : Particles)
                i->Update();

            redraw = true;
        }

        for(auto iter = Particles.begin(); iter != Particles.end(); )
            {
                if(!(*iter)->GetAlive())
                {
                    delete (*iter);
                    iter = Particles.erase(iter);
                }
                else
                    iter++;
            }

        if(redraw && al_event_queue_is_empty(event_queue))
        {
            for(auto i : Particles)
                i->Draw();

            al_draw_textf(myFont, al_map_rgb(0,200,0), 0, 10, NULL, "Mouse X: %i", mouseX);
            al_draw_textf(myFont, al_map_rgb(0,200,0), 0, 30, NULL, "Mouse Y: %i", mouseY);
            al_draw_textf(myFont, al_map_rgb(0,200,0), 0, 60, NULL, "Particle Count: %i", particleCount);

            al_flip_display();
            al_clear_to_color(al_map_rgb(0,0,0));
            redraw = false;
        } 
    }


    al_destroy_display(display);
    al_destroy_event_queue(event_queue);
    al_destroy_timer(myTimer);
    for(auto i : Particles)
        delete i;
    Particles.clear();

    return 0;
}

是的,代码很糟糕。似乎我对 C++ 背后的理论了解比实际实现它更多。但我猜我正在学习。

问题:

有人说我不能多次调用“新”和“删除”,因为这很糟糕。

粒子创建受到计时器的限制-我不能/不知道如何制作它,因此我可以控制粒子创建的速度。

我不希望有人为我创作,如果我可以阅读一些东西来帮助我理解或有人发布一些代码来学习/让我思考,那将非常有用?

【问题讨论】:

    标签: c++ system allegro5 particles


    【解决方案1】:

    您的粒子生成确实受到计时器的限制。您是在告诉 Allegro,如果在触发计时器事件时按下鼠标按钮,则生成一个粒子。您可以通过在每个计时器滴答声中创建多个粒子来提高粒子创建速率。

        for(int i = 0; i < rate; rate++)
        {
                randNum = (std::rand()+1 * ev.timer.count) % 50;
                std::cout << randNum << std::endl;
    
                if(mouseHold)
                {
                    Particle* particle = new Particle(mouseX + randNum, mouseY + randNum);
                    Particles.push_back(particle);
                }
        }
    

    然后只需使用可变速率来控制生成粒子的“速度”。这样做的缺点是绘制具有相同原始 X 和 Y 位置的多个粒子,但由于您还使用了 randNum,所以应该没问题。

    另一个选项可能更适合您的需求,具体取决于这些粒子的作用,它是使用计时器以更快的速度计时来生成您的粒子。当您检查 ALLEGRO_EVENT_TIMER 时,请执行

    if(ev.timer.source == timer)
    {
        redraw = true;
    }
    if (ev.timer.source == fasterTimer)
    {
        randNum = (std::rand()+1 * ev.timer.count) % 50;
        std::cout << randNum << std::endl;
    
        if(mouseHold)
        {
            Particle* particle = new Particle(mouseX + randNum, mouseY + randNum);
            Particles.push_back(particle);
        }
    }
    

    【讨论】:

    • 太棒了。我实际上实现了这一点,但并不完全知道该怎么做大声笑,谢谢,你也可以给我一个实际发生的事情吗?我有点知道,但要完全理解我很感激:D
    • 由于您的计时器设置为以 1/60 运行,因此您每秒将获得 60 个 ALLEGRO_TIMER_EVENTS。由于包含您的粒子创建的代码块在该检查中,因此您每秒最多可以获得 60 个粒子。通过使用具有更快滴答率的计时器,您可以生成更多粒子,如第二个解决方案所示。第一个解决方案会做同样的事情,通过每秒生成可变速率 * 60 个粒子。请查看fixbyproximity.com/2d-game-development-course(特别是第 4 部分),了解 Allegro 中时序的高级概述。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    相关资源
    最近更新 更多