Игра SFML тормозит при стрельбе пулями

Я делаю игру с астероидами на С++, используя SFML. У меня, кажется, проблема со стрельбой пулями. Хотя кажется, что класс работает каждый раз, когда пуля стреляет, игра значительно замедляется. Это код для космического корабля и пуль. Я просто не могу найти, что с ним не так! Спасибо за уделенное время.

Это Кодекс корабля:

#include "Spaceship.h"

Spaceship::Spaceship(void){}

Spaceship::~Spaceship(void){}

void Spaceship::LoadResources()
{

    if(!shipAnimImg.LoadFromFile("Resources/Images/SpaceshipAnimation.png"))
        std::cout <<"Could not locate the ship animation image" <<std::endl;

    if(!shipIdleImg.LoadFromFile("Resources/Images/SpaceshipIdle.png"))
        std::cout <<"Could not locate the ship idle image" <<std::endl;

    if(!bulletImg.LoadFromFile("Resources/Images/Bullet.png"))
        std::cout <<"Could not locate the bullet image" <<std::endl;

    shipSpr.SetImage(shipIdleImg);
    shipSpr.SetScale(0.5,0.5);
    shipSpr.SetCenter(shipIdleImg.GetWidth() / 2,shipIdleImg.GetHeight() / 2);

    x = DEFAULT_SCREENWIDTH / 2; 
    y = DEFAULT_SCREENHEIGHT / 2;

    shipSpr.SetPosition(x,y);
    shipSpr.SetRotation(90);

    std::cout<<shipSpr.GetCenter().x<<std::endl;
    std::cout<<shipSpr.GetCenter().y<<std::endl;

    vx = 0.2;
    vy = 0.2;

    isBulletOnScreen = false;
    isPressed = false;
}

void Spaceship::UnloadResources(){}

void Spaceship::Update(sf::RenderWindow &Window,sf::Event event)
{

    if (Window.GetInput().IsKeyDown(sf::Key::A))
    {
        shipSpr.Rotate(0.08);
    }

    if (Window.GetInput().IsKeyDown(sf::Key::D))
    {
        shipSpr.Rotate(-0.08);
    }

    if (Window.GetInput().IsKeyDown(sf::Key::W))
    {
        x += (cos(shipSpr.GetRotation() * (3.14159265/180.0)) *0.2);
        y -= (sin(shipSpr.GetRotation() * (3.14159265/180.0)) *0.2);
        shipSpr.SetPosition(x,y);
    }



    if (Window.GetInput().IsKeyDown(sf::Key::Space) && !isPressed)
    {   
    isBulletOnScreen = true;
    isPressed  = true;
    bullets.push_back(new Bullet(shipSpr.GetPosition().x,shipSpr.GetPosition().y,0.3,shipSpr.GetRotation(),bulletImg));
    }

    if (event.Type == sf::Event::KeyReleased)
    {
        isPressed  = false;
    }

    if(bullets.size() != 0)
    {
        for (int i=0; i<bullets.size(); i++)
        {
            bullets[i]->Update(Window,event);
            if ((bullets[i]->GetX() > DEFAULT_SCREENWIDTH + 40) || (bullets[i]->GetX() < 0 - 40) ||
                (bullets[i]->GetY() > DEFAULT_SCREENWIDTH + 40) || (bullets[i]->GetY() < 0 - 40))
                {
                    bullets.erase(bullets.begin() +i);
                }
        }
        std::cout<<bullets.size()<<std::endl;
    }
    std::cout<<bullets.size()<<std::endl;

}

void Spaceship::Draw(sf::RenderWindow &Window)
{
    if(isBulletOnScreen)
    for (int i=0; i<bullets.size(); i++)
    {
        Bullet *cur = bullets[i];
        bullets[i]->Draw(Window);
        std::cout<<bullets.size()<<std::endl;
    }

    Window.Draw(shipSpr);
}

А это для пули:

#include "Bullet.h"

Bullet::Bullet(void){}

Bullet::Bullet(float x,float y,float v,float r,sf::Image image)
{
    LoadResources(x,y,v,r,image);
}

Bullet::~Bullet(void){}

void Bullet::LoadResources(float x,float y,float v,float r , sf::Image image)
{
    this->x = x;
    this->y = y;
    this->v = v;

    bulletImg = image;
    bulletSpr.SetImage(bulletImg);
    bulletSpr.SetScale(0.5,0.5);
    bulletSpr.SetCenter(bulletImg.GetWidth() / 2,bulletImg.GetHeight() / 2);
    bulletSpr.SetPosition(x,y);
    bulletSpr.SetRotation(r);
}

void Bullet::UnloadResources(){}

void Bullet::Update(sf::RenderWindow &Window,sf::Event event)
{
    x += (cos(bulletSpr.GetRotation() * (3.14159265/180.0)) *v);
    y -= (sin(bulletSpr.GetRotation() * (3.14159265/180.0)) *v);

    bulletSpr.SetPosition(x,y);
}

void Bullet::SetX(float x)
{
    this->x = x;
}

void Bullet::SetY(float y)
{
    this->y = y;
}

void Bullet::SetRotation(float r)
{
    rotation = r;
}

float Bullet::GetX()
{
    return x;
}

float Bullet::GetY()
{
    return y;
}

void Bullet::Draw(sf::RenderWindow &Window)
{
    Window.Draw(bulletSpr);
}

РЕДАКТИРОВАТЬ: изменен код, так что он загружает изображение внутри класса космического корабля и передает его в ресурсы пули после его создания. Однако проблема все еще остается той же. Игра становится все медленнее с каждым выстрелом пули и остается медленной до тех пор, пока ее не стирают.


person user2315574    schedule 24.04.2013    source источник
comment
Замедляется ли он на время действия пули или только в момент выстрела?   -  person Joseph Mansfield    schedule 24.04.2013
comment
Он замедляется, пока на экране есть пули. Даже после изменения loadfromfile пули, которая загружается и передается с космического корабля только один раз, я все равно получаю такое же замедление. Скорость программы возвращается к нормальной, когда все пули удаляются из сцены.   -  person user2315574    schedule 24.04.2013


Ответы (2)


1. Вы загружаете изображение Bullet PNG с диска каждый раз, когда создаете новый объект (часто, если вам нравится снимать). Загрузка с диска, вероятно, будет очень медленной. Вместо этого попробуйте повторно использовать одно и то же изображение несколько раз!

Возможно, вы могли бы вытащить функцию LoadFromFile из LoadResources и поместить ее куда-нибудь, где она будет действовать на протяжении всей игры. Тогда просто пусть LoadResources ссылается на это место всякий раз, когда нужно создать новую пулю. То же самое касается любых других изображений или ресурсов, которые можно повторно использовать в вашей игре.

2. Я также заметил, что в вашем коде есть std::cout. Попробуйте удалить все те, которые находятся в цикле рендеринга, так как печать идет медленно.

for (int i=0; i<bullets.size(); i++)
{
    Bullet *cur = bullets[i];
    bullets[i]->Draw(Window);
    std::cout<<bullets.size()<<std::endl; // This is going to be slow
}

3. Вы также можете взглянуть на вектор bullets. При добавлении к нему маркеров push_back изменяет размер вектора, а это каждый раз требует некоторого выделения и освобождения памяти. Лучшим подходом было бы создать место для максимального количества маркеров в начале (используя, например, функцию resize), чтобы вектор не менял размер всякий раз, когда создается маркер.

if (Window.GetInput().IsKeyDown(sf::Key::Space) && !isPressed)
{   
    isBulletOnScreen = true;
    isPressed  = true;
    bullets.push_back(new Bullet(...); // avoid this
}
person Victor Sand    schedule 24.04.2013
comment
Спасибо, что нашли время ответить. Даже после изменения png для загрузки только один раз в классе космического корабля и передачи при создании пули, я все равно получаю такое же замедление, пока в сцене есть объекты пули. - person user2315574; 24.04.2013
comment
Добавлено в ответ. Попробуйте удалить std::cout! - person Victor Sand; 24.04.2013
comment
Я удалил все выходные данные консоли, которые у меня были, но у меня все еще есть та же проблема. С каждой пулей, которую я выпускаю, она становится все медленнее и медленнее, пока пуля не стирается! - person user2315574; 24.04.2013
comment
Очень плохо. Я думаю, что загрузка с диска и couts значительно замедлила его, но где-то там должно быть еще большее узкое место. Я сам не использовал SFML, поэтому не знаю, как он выполняет рендеринг и т. д. - person Victor Sand; 24.04.2013

Каждый раз, когда вы вызываете новую пулю

Bullet::Bullet(float x,float y,float v,float r)
{
    LoadResources(x,y,v,r);
}

Вы также вызываете LoadResources(x,y,v,r), который вызывает

bulletImg.LoadFromFile("Resources/Images/Bullet.png")

и этот вызов читает файл с диска, что является очень медленной операцией, на порядок медленнее, чем что-либо еще, поэтому ваша программа останавливается на время загрузки.

person Community    schedule 24.04.2013
comment
Спасибо за ответ на вопрос, но даже после того, как я изменил изображение пули, чтобы оно загружалось один раз в классе космического корабля, и передал его в пуле при загрузке ресурсов, я все еще сталкиваюсь с тем же замедлением, когда в сцене есть объекты пули. - person user2315574; 24.04.2013
comment
@user2315574 user2315574 Вы вызываете код, который не публиковали, поэтому я не могу знать, в чем может быть проблема. Возможно, вы создаете слишком много пуль одновременно. - person ; 24.04.2013
comment
Я тоже согласен с Армином. Просто выполните некоторую отладку остальной части кода и следите за тем, где пули излишне/случайно копируются - может быть, в какой-то функции обнаружения столкновений? - person psibar; 26.04.2013