簡體   English   中英

SFML-嘗試從矢量繪制精靈時程序崩潰

[英]SFML - program crashes when trying to draw sprite from vector

我正在編寫這個相對簡單的程序,當按下空格鍵時,可以從移動的角色發射小彈丸。

程序編譯無誤(在代碼塊中),並運行到按下空格鍵為止。 該程序沒有啟動彈丸,而是立即崩潰。

我認為我已經能夠將墜機事件隔離到將彈丸繪制到屏幕的那條線上(第83頁)。 我只是在前后的行上使用了cout語句,而第二條語句沒有顯示。

for (int ii = 0; ii < inMotion.size(); ii++)
{
    window.draw(inMotion[ii].bulletSprite);
}

我認為解決此問題將需要我的所有代碼,因此我已發布了所有代碼。

#include <iostream>
#include <SFML/Graphics.hpp>
#include <string.h>
#include <math.h>
#include <vector>

using namespace std;
class Projectile
{
public:
    Projectile(int, string);
    void moveBullet();
    sf::Sprite bulletSprite;
private:
    sf::Texture bulletTexture;
    int speed;
    string bulletTextureString;
};

Projectile::Projectile(int s, string t)
{
    speed = s;
    bulletTextureString = t;
    if(!bulletTexture.loadFromFile((bulletTextureString).c_str()))
    {
        cout << "error";
    }
    bulletSprite.setTexture(bulletTexture);
}
void Projectile::moveBullet()
{
    bulletSprite.move(speed, 0);
}

class thePlayer
{
public:
    void Fire(sf::Time);
    void Walk();
    void Draw(sf::RenderWindow&);
    void Create(string);
    sf::Time lastShot;
private:
    vector<Projectile> inMotion;
    sf::Texture playerTexture;
    sf::Sprite playerSprite;
    string playerTextureString;
    int moveSpeed = 5;

}; 

void thePlayer::Create(string s)
{
    playerTextureString = s;

    if(!playerTexture.loadFromFile((playerTextureString).c_str()))
    {
        cout << "error";
    }
    playerSprite.setTexture(playerTexture);
}
void thePlayer::Fire(sf::Time time)
{
    sf::Time shotDelay = sf::milliseconds(100);
    if(time - lastShot >= shotDelay)
    {
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
        {
            Projectile bullet(15, "fireball.png");
            bullet.bulletSprite.setPosition(playerSprite.getPosition());
            inMotion.push_back(bullet);
        }
    } 
    for(int ii = 0; ii < inMotion.size(); ii++)
    {
        inMotion[ii].moveBullet();
    }
}
void thePlayer::Draw(sf::RenderWindow& window)
{
    for (int ii = 0; ii < inMotion.size(); ii++)
    {
        window.draw(inMotion[ii].bulletSprite);
    }
    window.draw(playerSprite);
}
void thePlayer::Walk()//awsd standart movement
{
    int x = 0;
    int y = 0;
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    {
        x-= moveSpeed;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    {
        x+= moveSpeed;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
    {
        y-= moveSpeed;
    }
    else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
    {
        y+= moveSpeed;
    }
    playerSprite.move(x, y);
}

class Game
{
public:
    void Update(sf::RenderWindow&, sf::Time);
    void Start(sf::Time);
    sf::Clock clock;
    thePlayer player;

private:

};

void Game::Start(sf::Time time)
{
    player.Create("block.png");
    player.lastShot = time;
}
void Game::Update(sf::RenderWindow& window, sf::Time time)
{
    player.Fire(time);
    player.Walk();
    player.Draw(window);
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(1000, 1000), "Menu");
    window.setFramerateLimit(60);
    Game theGame;
    sf::Clock clock;
    sf::Time startTime = clock.restart();
    theGame.Start(startTime);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color::White);
        sf::Time elapsed = clock.getElapsedTime();
        theGame.Update(window, elapsed);
        window.display();
    }
    return 0;
}

非常感謝幫忙。

編輯:我嘗試使用調試器,但什么都找不到。 鏈接到一篇有關代碼塊調試的好文章的鏈接將非常有用。

我自己解決了。 我發現必須通過指針引用Bullet類,並確保紋理也是公共的。 我也錯誤地使用了構造函數,並且擺脫了這些構造函數。

我的大概解決方案是...

void thePlayer::Fire(sf::Time time)
{
    sf::Time shotDelay = sf::milliseconds(100);
    if(time - lastShot >= shotDelay)
    {
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
        {
            Projectile *bullet = new Bullet;
            bullet->bulletSprite.setPosition(playerSprite.getPosition());
            inMotion.push_back(bullet);
        }
    } 
    for(int ii = 0; ii < inMotion.size(); ii++)
    {
        inMotion[ii]->moveBullet();
    }

還必須在類中更改向量聲明

//...
vector<Bullet*> Bullets;
//...

再次感謝那些試圖回答的人。

好吧,您編寫的游戲代碼非常錯誤!

我的建議:

  • 您應該創建一個球員和一個子彈班,

  • 每個類分別作為渲染方法和更新方法-更新方法具有dt(到最后一幀為止的經過時間)參數,

  • 播放器類具有“移動”和“觸發”方法,

  • 在游戲循環中,您首先要讀取輸入(並在需要時調用move或fire方法),更新所有對象(玩家和項目符號的位置)並繪制所有內容,

  • move方法應使玩家具有速度,

  • 射擊方法應以速度制造子彈,

  • 更新方法應計算新位置(具有速度和dt),

  • 玩家和子彈可能來自基礎游戲元素類(女巫計算位置,碰撞等)。

您必須重置時鍾:

sf::Time elapsed = clock.restart();

而且,您應該只加載一次射彈的紋理,並在Projectile類的所有實例中使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM