2013-04-24 2 views
1

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

EDIT: Изменен код так, чтобы он загружает изображение внутри космического корабля класса и проходов это к ресурсам Bullet после его создания. Проблема все же остается прежней. Игра становится все более медленной каждый раз, когда пуля снимается, и она остается медленной, пока она не будет стерта.

+0

Это замедляется на время пули или только в момент его увольнения? –

+0

Он замедляется, пока на экране появляются пули. Даже после изменения loadfromfile пули, которую нужно загрузить и передать с космического корабля, только один раз, я все равно получаю такое же замедление. Скорость программы возвращается в нормальное состояние, когда все пули удаляются из сцены. – user2315574

ответ

3

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 
} 
+0

Спасибо, что нашли время, чтобы ответить.Даже после изменения png, который будет загружен только один раз в классе космического корабля и передан при создании пули, я все равно получаю такое же замедление, пока в сцене появляются объекты пули. – user2315574

+0

Добавлен ответ. Попробуйте удалить std :: cout! –

+0

Я удалил каждый консольный вывод, который у меня был, но у меня все еще такая же проблема. С каждой пулей я стреляю, она все больше и больше замедляется, пока пуля не стирается! – user2315574

1

Everytime вы вызываете новую пулю

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

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

+0

Благодарим вас за ответ на этот вопрос, но даже после того, как я изменил изображение пули, которое будет загружено один раз в классе космического корабля и передано в пуле при загрузке ресурсов, я все равно сталкиваюсь с тем же замедлением, в то время как на сцене появляются объекты пули. – user2315574

+0

@ user2315574 Вы вызываете код, который вы не отправляли, поэтому я не могу знать, в чем проблема. Возможно, вы создаете слишком много пуль одновременно. – 2013-04-24 14:09:36

+0

Я также согласен с Armin. Просто выполните некоторую отладку на остальной части кода и следите, где «Bullets» излишне/случайно скопированы - возможно, в некоторой функции обнаружения столкновения? – psibar

Смежные вопросы