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

Я делаю игру астероидов в C ++, используя 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);
}

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

1

Решение

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
}
3

Другие решения

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

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")

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

1