【问题标题】:SFML Game Slows Down When Shooting BulletsSFML 游戏在射击子弹时变慢
【发布时间】:2013-04-24 13:04:56
【问题描述】:

我正在使用 SFML 用 C++ 制作小行星游戏。我似乎有射击子弹的问题。尽管每次射击子弹时课程似乎都有效,但游戏速度显着减慢。这是宇宙飞船和子弹的代码。我似乎无法找到它有什么问题!感谢您的宝贵时间。

这是船的代码:

#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);
}

编辑:更改了代码,以便将图像加载到 Spaceship 类中,并在创建后将其传递给 Bullet 的资源。问题仍然是一样的。每次发射子弹,游戏就会变得越来越慢,直到被清除为止。

【问题讨论】:

  • 它是在子弹持续时间内减速还是仅在发射时减速?
  • 当屏幕上有子弹时它会变慢。即使在更改要加载的子弹的 loadfromfile 并仅从宇宙飞船传入一次后,我仍然会遇到相同的减速。当所有的子弹从场景中移除时,程序的速度就会恢复正常。

标签: c++ sfml bullet


【解决方案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
}

【讨论】:

  • 感谢您花时间回答。即使将 png 更改为仅在 spaceship 类中加载一次并在创建子弹时传递,当场景中有子弹对象时,我仍然会遇到同样的减速。
  • 添加到答案中。尝试删除 std::cout!
  • 我已经删除了所有的控制台输出,但我仍然遇到同样的问题。我射出的每一颗子弹都会变得越来越慢,直到子弹被抹去!
  • 太糟糕了。我认为从磁盘和 couts 的加载显着减慢了速度,但那里一定存在更大的瓶颈。我自己没用过SFML,所以不知道它是怎么渲染等的。
【解决方案2】:

每次调用一个新的 Bullet

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

并且该调用从磁盘读取文件,这是一个非常慢的操作,比其他任何操作都慢一个数量级,因此您的程序在加载期间停止。

【讨论】:

  • 感谢您回答问题,但即使我将子弹图像更改为在飞船类中加载一次并在加载资源时将其传递给子弹后,我仍然遇到同样的减速,而有场景中的子弹对象。
  • @user2315574 你正在调用你没有发布的代码,所以我不知道可能是什么问题。也许你同时产生了太多子弹。
  • 我也同意阿明的观点。只需对其余代码进行一些调试,并注意“Bullets”被不必要/意外复制的地方 - 也许在某些碰撞检测功能中?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 2015-05-17
  • 1970-01-01
相关资源
最近更新 更多