2017-09-23 44 views
1

我在Linux Mint 18.1上使用C++ 17學習了使用GUI的SFML 2.3.2。作爲Hello World之後的第二個項目,我試圖重新制作Snake,這款遊戲舊手機已經預裝了。大部分的東西一直工作到現在,除了一些小例外,我將不得不在稍後處理,一些由遊戲尚未完全完成。使用SFML中的精靈不顯示圖像

只是爲了確保正確理解此事,因爲我以前從未使用過較低級語言的GUI和圖像。首先將圖像加載到紋理中,然後將紋理添加到sprite,然後將該sprite繪製到窗口上?

該程序完美編譯,正確初始化所有內容,並且運行時沒有任何重大不明原因的問題。除了圖像不顯示。精靈在那裏,並以默認的單色背景顏色顯示,但不顯示任何圖像。

我該怎麼做,我該如何解決?謝謝!

// HEADERS 
#include <iostream> 
#include <SFML/Graphics.hpp> 
#include <SFML/Graphics/Color.hpp> 
#include <SFML/Graphics/Font.hpp> 
#include <SFML/Graphics/Image.hpp> 
#include <SFML/Graphics/Rect.hpp> 
#include <SFML/Graphics/Sprite.hpp> 
#include <SFML/Graphics/Texture.hpp> 
#include <SFML/System/String.hpp> 
#include <SFML/Window/Keyboard.hpp> 

// CREATE NEW FONT 
sf::Font create_font() 
{ 
    sf::Font f; 
    bool id = f.loadFromFile("/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf"); 

    if (id == false) 
    { 
     std::cerr << "Font:\tCould not be loaded." << std::endl; 
    } 
    else 
    { 
     std::cerr << "Font:\tLoaded successfully." << std::endl; 
    } 

    return f; 

} 

// CREATE NEW SPRITE USING TEXTURE, GIVEN ARE PATH WITH COORDINATES AND DIMENSIONS 
sf::Sprite load_img(std::string path, long x, long y, long w, long h) 
{ 
    sf::Texture t; 
    bool id = t.loadFromFile(path); 

    if (id == false) 
    { 
     std::cerr << "Texture:\t" << path << "\tFailed to load." << std::endl; 
    } 
    else 
    { 
     std::cerr << "Texture:\t" << path << "\tLoaded successfully." << std::endl; 
    } 

    sf::Sprite s(t); 
    s.setTextureRect(sf::IntRect((int)x, (int)y, (int)w, (int)h)); 
    s.setPosition(x, y); 
    return s; 
} 


// MAIN FUNCTION 
int main() 
{ 
    // DECLARING/DEFINING VARIABLES 
    unsigned long window_width = 512; 
    unsigned long window_height = 512; 
    unsigned long score = 0; 
    unsigned long head_old_position_x, head_old_position_y; 
    std::string title = "Snek"; 
    std::string wdir = "/home/kate/Documents/coding/snek/"; 

    // WINDOW 
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title); 
    window.setFramerateLimit(60); 

    // SPRITES 
    sf::Sprite background = load_img(wdir + "img/background.png", 0, 0, 512, 512); 
    sf::Sprite head = load_img(wdir + "img/head.png", 47, 39, 8, 8); 
    sf::Sprite body = load_img(wdir + "img/body.png", 39, 39, 8, 8); 
    sf::Sprite poison = load_img(wdir + "img/poison.png", 119, 119, 8, 8); 
    sf::Sprite trap = load_img(wdir + "img/trap.png", 159, 159, 8, 8); 
    sf::Sprite candy = load_img(wdir + "img/candy.png", 199, 199, 8, 8); 

    // FONT 
    sf::Font font = create_font(); 

    // TEXT 
    sf::Text score_display(title, font, 20); 
    sc// HEADERS 
#include <iostream> 
#include <SFML/Graphics.hpp> 
#include <SFML/Graphics/Color.hpp> 
#include <SFML/Graphics/Font.hpp> 
#include <SFML/Graphics/Image.hpp> 
#include <SFML/Graphics/Rect.hpp> 
#include <SFML/Graphics/Sprite.hpp> 
#include <SFML/Graphics/Texture.hpp> 
#include <SFML/System/String.hpp> 
#include <SFML/Window/Keyboard.hpp> 

// CREATE NEW FONT 
sf::Font create_font() 
{ 
    sf::Font f; 
    bool id = f.loadFromFile("/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf"); 

    if (id == false) 
    { 
     std::cerr << "Font:\tCould not be loaded." << std::endl; 
    } 
    else 
    { 
     std::cerr << "Font:\tLoaded successfully." << std::endl; 
    } 

    return f; 

} 

// CREATE NEW SPRITE USING TEXTURE, GIVEN ARE PATH WITH COORDINATES AND DIMENSIONS 
sf::Sprite load_img(std::string path, long x, long y, long w, long h) 
{ 
    sf::Texture t; 
    bool id = t.loadFromFile(path); 

    if (id == false) 
    { 
     std::cerr << "Texture:\t" << path << "\tFailed to load." << std::endl; 
    } 
    else 
    { 
     std::cerr << "Texture:\t" << path << "\tLoaded successfully." << std::endl; 
    } 

    sf::Sprite s(t); 
    s.setTextureRect(sf::IntRect((int)x, (int)y, (int)w, (int)h)); 
    s.setPosition(x, y); 
    return s; 
} 


// MAIN FUNCTION 
int main() 
{ 
    // DECLARING/DEFINING VARIABLES 
    unsigned long window_width = 512; 
    unsigned long window_height = 512; 
    unsigned long score = 0; 
    unsigned long head_old_position_x, head_old_position_y; 
    std::string title = "Snek"; 
    std::string wdir = "/home/kate/Documents/coding/snek/"; 

    // WINDOW 
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title); 
    window.setFramerateLimit(60); 

    // SPRITES 
    sf::Sprite background = load_img(wdir + "/img/background.png", 0, 0, 512, 512); 
    sf::Sprite head = load_img(wdir + "/img/head.png", 47, 39, 8, 8); 
    sf::Sprite body = load_img(wdir + "/img/body.png", 39, 39, 8, 8); 
    sf::Sprite poison = load_img(wdir + "/img/poison.png", 119, 119, 8, 8); 
    sf::Sprite trap = load_img(wdir + "/img/trap.png", 159, 159, 8, 8); 
    sf::Sprite candy = load_img(wdir + "/img/candy.png", 199, 199, 8, 8); 

    // FONT 
    sf::Font font = create_font(); 

    // TEXT 
    sf::Text score_display(title, font, 20); 
    score_display.setString(std::to_string(score)); 
    score_display.setPosition(5, 5); 

    // LOOP 
    while (window.isOpen()) 
    { 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
      { window.close(); } 

      head_old_position_x = head.getPosition().x; 
      head_old_position_y = head.getPosition().y; 

      // MOVEMENT BASED ON KEYBOARD INPUT 
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 
      { 
       head.setPosition(head.getPosition().x - 8, head.getPosition().y); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) 
      { 
       head.setPosition(head.getPosition().x, head.getPosition().y - 8); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) 
      { 
       head.setPosition(head.getPosition().x + 8, head.getPosition().y); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) 
      { 
       head.setPosition(head.getPosition().x, head.getPosition().y + 8); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 


      if (body.getPosition().x == candy.getPosition().x && body.getPosition().y == candy.getPosition().y) 
      { 
       score ++; 
       score_display.setString(std::to_string(score)); 
      } 


      // REFRESH WINDOW 
      window.clear(); 
      window.draw(background); 
      window.draw(head); 
      window.draw(body); 
      window.draw(poison); 
      window.draw(trap); 
      window.draw(candy); 
      window.draw(score_display); 
      window.display(); 
     } 
    } 

    return 0; 
} 
ore_display.setString(std::to_string(score)); 
    score_display.setPosition(5, 5); 

    // LOOP 
    while (window.isOpen()) 
    { 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
      { window.close(); } 

      head_old_position_x = head.getPosition().x; 
      head_old_position_y = head.getPosition().y; 

      // MOVEMENT BASED ON KEYBOARD INPUT 
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 
      { 
       head.setPosition(head.getPosition().x - 8, head.getPosition().y); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) 
      { 
       head.setPosition(head.getPosition().x, head.getPosition().y - 8); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) 
      { 
       head.setPosition(head.getPosition().x + 8, head.getPosition().y); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) 
      { 
       head.setPosition(head.getPosition().x, head.getPosition().y + 8); 
       body.setPosition(head_old_position_x, head_old_position_y); 
      } 


      if (body.getPosition().x == candy.getPosition().x && body.getPosition().y == candy.getPosition().y) 
      { 
       score ++; 
       score_display.setString(std::to_string(score)); 
      } 


      // REFRESH WINDOW 
      window.clear(); 
      window.draw(background); 
      window.draw(head); 
      window.draw(body); 
      window.draw(poison); 
      window.draw(trap); 
      window.draw(candy); 
      window.draw(score_display); 
      window.display(); 
     } 
    } 

    return 0; 
} 
+0

控制檯中是否有任何消息? –

+0

不顯示圖像的常見原因是因爲紋理超出了範圍,或者無法加載。 –

+0

@ArnavBorborah不,沒有任何SFML功能。我自己的錯誤檢查確認一切*應該*按預期工作。 – Katembers

回答

0

好吧,我想我已經得到它了。

可能什麼也看不見了,因爲你把所有繪製的東西事件循環內

試圖把這些東西在while(window.isOpen())環範圍。

+0

是的。而已!謝謝!最後:D在上週瘋狂地瀏覽了我的代碼,但無法找到它。 – Katembers

0

您的紋理超出了範圍,有關更多詳細信息,請參閱When is an object "out of scope"?。你在load_img函數中聲明瞭紋理,但是在退出load_img並返回精靈之後,sf::Texture t;被刪除。

所以這裏是一個更新函數,其中您將紋理存儲在load_img函數之外並通過引用傳遞它。只顯示相關部分。首先將紋理傳遞給load_img函數。刪除sf::Texture t;

sf::Sprite load_img(std::string path, long x, long y, long w, long h, sf::Texture& t) 
{ 
    bool id = t.loadFromFile(path); 
    [...] 
} 

聲明一個紋理並將其傳遞給load_img函數。

sf::Texture headtexture; 
sf::Sprite head = load_img(wdir + "img/head.png", 47, 39, 8, 8, headtexture); 

如果你對所有的精靈都這樣做,它的工作原理和正確顯示圖像/精靈。

編輯 25月 - 2017年

根據該意見,在這裏是沒有功能的最小工作示例:

// HEADERS 
#include <iostream> 
#include <SFML/Graphics.hpp> 
#include <SFML/Graphics/Color.hpp> 
#include <SFML/Graphics/Font.hpp> 
#include <SFML/Graphics/Image.hpp> 
#include <SFML/Graphics/Rect.hpp> 
#include <SFML/Graphics/Sprite.hpp> 
#include <SFML/Graphics/Texture.hpp> 
#include <SFML/System/String.hpp> 
#include <SFML/Window/Keyboard.hpp> 

// MAIN FUNCTION 
int main() 
{ 
    // DECLARING/DEFINING VARIABLES 
    unsigned long window_width = 512; 
    unsigned long window_height = 512; 
    std::string title = "Snek"; 
    std::string wdir = "/home/kate/Documents/coding/snek/"; 

    // WINDOW 
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title); 
    window.setFramerateLimit(60); 

    // SPRITES 
    sf::Texture headtexture; 
    sf::Sprite head; 

    headtexture.loadFromFile(wdir + "img/head.png"); 
    head.setTexture(headtexture); 
    head.setTextureRect(sf::IntRect(47, 39, 8, 8)); 
    head.setPosition(30, 30); 

    // LOOP 
    while (window.isOpen()) 
    { 
     sf::Event event; 
     while (window.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
      { window.close(); } 

      // REFRESH WINDOW 
      window.clear(); 
      window.draw(head); 
      window.display(); 
     } 
    } 

    return 0; 
} 
+0

我已經懷疑已經是昨天了,並且把所有東西都移到了'int main()'中,以確保100%。精靈以默認的單色背景顏色顯示,但圖像不存在。基本上,我看到的只是窗口的黑色背景。 – Katembers

+0

是的,但是目前您在函數中定義了紋理,並且在退出時會超出範圍,導致未定義的行爲。 –

+0

我改變了它,以便紋理和精靈都在'int main()'中獨佔使用。它永遠不會去其他任何地方。仍然不起作用。 – Katembers

0

也許你已經失去了參考你的紋理。在你的情況下,紋理是load_img()函數中的局部變量。

你應該保持你的紋理加載和可用,而任何精靈正在使用它。

我建議您閱讀SFML教程的this部分,其中解釋了此問題。

+0

我讀過評論,你把所有東西都移到'main'。你能用那個代碼更新嗎?也許這樣我們可以發現任何錯誤 – alseether

+0

這是問題的一部分,但主要問題在其他地方。查看我標記爲解決方案的答案。這是這裏的主要問題。 – Katembers