Search code examples
c++imageuser-interfacesfmlc++17

Images not displayed using sprites in SFML


I've picked up SFML 2.3.2 on Linux Mint 18.1 using C++17 to learn working with GUIs. As a second project after Hello World, I'm trying to reproduce Snake, that game old phones had pre-installed. Most stuff worked until now, with a few minor exceptions that I will have to deal with later, some caused by the game not being fully finished yet.

Just to be sure that I understand the matter correctly, as I've never worked with GUIs and Images in a lower-level language before. First you load your image into the texture, then you add the texture to a sprite, and then you draw that sprite onto the window?

The program compiles flawlessly, initializes everything correctly, and runs with no major unexplained issues. Except that the images don't show. The sprites are there and shown in their default mono-chrome background color, but don't show any images.

What do I do wrong, and how do I fix it? Thanks!

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

Solution

  • Ok, i think i've got it.

    Possibly nothing is shown because you have all drawing stuff inside event loop

    Try to put that stuff in the while(window.isOpen()) loop scope.