2014-05-17 33 views
0

我正在寫這個相對簡單的程序,以便在空格鍵被按下時從移動的字符中射出一個小的子彈。SFML - 試圖從矢量繪製精靈時程序崩潰

該程序編譯沒有任何錯誤(在代碼塊中)並運行,直到按下空格鍵。該程序不是發射彈丸,而是迅速崩潰。

我想我已經能夠將碰撞隔離到我將彈丸畫到屏幕的那一行(ln.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; 
} 

非常感謝您的幫助。

編輯:我試過使用調試器,但無法找出任何東西。一個關於代碼塊調試的好文章的鏈接會很棒。

回答

1

我能夠自己解決這個問題。我發現我必須通過指針引用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; 
//... 

,並感謝改變矢量聲明在課堂上誰試圖回答的人。

0

嗯,你編碼的遊戲相當不對!

我建議什麼:

  • 您應該創建一個播放器和子彈類,

  • 每個類的渲染方法和更新方法 - 升級方法有DT(經過時間直到最後一幀)的參數,

  • 播放器類有一個「移動」和「火」的方法,

  • 在遊戲循環中,您首先讀取輸入(並根據需要調用移動或火焰方法),更新所有對象(玩家和子彈位置)並繪製所有對象,移動方法應給予玩家速度,

  • 火法應該創建速度子彈,

  • 更新方法應該計算新的位置(與速度和DT),

  • 播放器和子彈可以從基礎的遊戲元素類衍生物(女巫計算位置,碰撞,等等...)。

+0

謝謝你的迴應。雖然我同意我的代碼可以寫得更好,但是您不回答我的問題。我希望能夠更深入地瞭解究竟是什麼導致程序崩潰。 –

+0

是的,但我已經試過你的代碼(在OSX下) - 它編譯時,玩家根據鍵移動,但子彈不起作用。 –

0

你必須重新設置時鐘:

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

你應該裝載炮彈的質地只有一次,並在彈類的所有實例都使用它。

+0

這沒有用。簡單地重置時鐘就是防止拋射物從不發射(因此不會調用導致崩潰的功能)。你的答案背後有沒有其他想法? –

+0

對不起,我以爲'elapsed'必須包含自上一幀以來的時間。只有現在我意識到你正在使用固定的時間步(我不推薦)。 一個問題可能是你沒有更新'lastShot',並且在每個幀中都創建了一個炮彈。 我建議你在第83行放置一個斷點,並注意向量是否有正確的數據。 – DarkPhantom