2017-09-23 10 views
1

J'ai choisi SFML 2.3.2 sur Linux Mint 18.1 en utilisant C++ 17 pour apprendre à travailler avec des interfaces graphiques. Comme deuxième projet après Hello World, j'essaye de reproduire Snake, ce jeu de vieux téléphones avait pré-installé. La plupart des choses ont fonctionné jusqu'à maintenant, avec quelques exceptions mineures que je devrai faire face plus tard, certaines causées par le jeu n'étant pas encore complètement fini. Juste pour être sûr que je comprends bien le problème, car je n'ai jamais travaillé avec des interfaces graphiques et des images dans un langage de niveau inférieur avant. D'abord vous chargez votre image dans la texture, puis vous ajoutez la texture à un sprite, puis vous dessinez ce sprite sur la fenêtre?Images non affichées à l'aide de sprites dans SFML

Le programme compile parfaitement, initialise tout correctement et s'exécute sans problème majeur inexpliqué. Sauf que les images ne montrent pas. Les sprites sont présents et affichés dans leur couleur de fond mono-chrome par défaut, mais ne montrent aucune image.

Qu'est-ce que je fais de mal, et comment puis-je le réparer? Merci!

// 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

Y a-t-il des messages dans la console? –

+0

Les raisons habituelles pour les images non affichées sont les suivantes: la texture est hors de portée ou n'a pas pu être chargée. –

+0

@ArnavBorborah Non, il n'y a rien de l'une des fonctions SFML. Ma propre vérification d'erreur confirme que tout * aurait * fonctionné comme prévu. – Katembers

Répondre

0

Ok, je pense que je l'ai.

Peut-être rien est montré parce que vous avez tous trucs dessin à l'intérieur de boucle d'événements

Essayez de mettre ce genre de choses dans le cadre de la boucle while(window.isOpen()).

+0

OUI. C'est tout! Merci! Enfin: D passait par mon code comme un fou la semaine dernière et ne pouvait pas le trouver. – Katembers

0

Votre texture est hors de portée, voir When is an object "out of scope"? pour plus de détails. Vous déclarez la texture dans la fonction load_img, mais sf::Texture t; est supprimé après avoir quitté load_img et renvoyé l'image-objet.

Voici donc une fonction mise à jour dans laquelle vous stockez la texture en dehors de la fonction load_img et la transmettez par référence. Seules les parties pertinentes sont montrées. Tout d'abord, passez la texture à la fonction load_img. Supprimez le 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); 
    [...] 
} 

Déclarez une texture et le transmettre à la fonction load_img.

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

Si vous faites cela pour tous vos sprites, cela fonctionne et montre les images/sprites correctement.

Modifier 25-Sep-2017

Sur la base des commentaires, voici un exemple de travail minimum sans fonctions:

// 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

Je m'en doutais déjà et j'ai tout transféré dans 'int main()' juste pour être sûr à 100%. Les sprites s'affichent avec leur couleur d'arrière-plan mono-chrome par défaut, mais l'image n'est pas présente. Fondamentalement, tout ce que je vois, c'est le fond noir de la fenêtre. – Katembers

+0

Oui, mais vous définissez actuellement la texture à l'intérieur de la fonction et elle sort du cadre lorsque vous la quittez, ce qui conduit à un comportement indéfini. –

+0

Je l'ai modifié pour que les textures et les sprites soient utilisés exclusivement dans 'int main()'. Ça ne va jamais ailleurs. Ça ne marche toujours pas. – Katembers

0

Probablement que vous avez perdu la référence à votre texture. Dans votre cas, la texture est une variable locale dans la fonction load_img().

Vous devriez garder votre texture chargée et disponible pendant que n'importe quel sprite l'utilise.

Je vous recommande de lire la section this du tutoriel SFML où ce problème est expliqué.

+0

J'ai lu dans les commentaires que vous avez tout déplacé vers 'main'. Pourriez-vous mettre à jour avec ce code? peut-être de cette façon, nous pouvons affiner toute erreur – alseether

+0

Cela faisait partie du problème, mais le problème principal était ailleurs. Voir la réponse que j'ai marquée comme solution. C'était le problème principal ici. – Katembers