Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sprite from Drawable object not appearing in window  (Read 1684 times)

0 Members and 1 Guest are viewing this topic.

HpHydra

  • Newbie
  • *
  • Posts: 2
    • View Profile
Sprite from Drawable object not appearing in window
« on: February 04, 2025, 07:02:33 am »
Hello, I am working on a project using SFML 3.0.0 that involves creating a class that inherits Drawable. The class simply has a Texture and a Sprite with the Texture being loaded from a png file. However, when I create an instance of the class in my main function and draw it in the window loop, nothing appears. I am on MacOs Sequoia (15.2). I've created a minimal example that reproduces my problem so here it is:

MyDrawable.cpp:
Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <iostream>

class MyDrawable : public sf::Drawable {
public:
    MyDrawable();
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
private:
    sf::Texture texture;
    sf::Sprite sprite;
};

MyDrawable::MyDrawable() : sprite(texture) {
    if (!texture.loadFromFile("image.png")) {
        std::cerr << "Error loading texture!" << std::endl;
    } else {
        sprite.setTexture(texture);
    }
}

void MyDrawable::draw(sf::RenderTarget& target, sf::RenderStates states) const {
    target.draw(sprite, states);
}

main.cpp:
Code: [Select]
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include "MyDrawable.cpp"

int main() {
    sf::RenderWindow window(sf::VideoMode({800, 800}), "Window");
    MyDrawable drawable;
   
    while (window.isOpen()) {
        while (const std::optional event = window.pollEvent())
        {
            if (event->is<sf::Event::Closed>())
                window.close();
        }

        window.clear(sf::Color::Black);
        window.draw(drawable);
        window.display();
    }

    return 0;
}

Here's some debugging steps I've tried so far:
  • I checked the size of the Texture after it was loaded which was 22x22 (correct for the image I'm using) but then I checked the local bounds of the sprite after applying the texture to it and they were 0x0.
  • After creating my drawable object in the main file, I saved the image back to a file by calling sprite.getTexture().copyToImage().saveToFile() and the output image is the same as the one that was uploaded to the texture.
  • I also created a texture and sprite directly in the main file with the texture loading the same image, and when I draw that one it shows in the window no problem.

I've been trying to solve this with no luck, on one hand if the sprite has local bounds of 0x0 that makes me think the sprite is not correctly pointing to my texture. But on the other hand, calling getTexture() on the sprite and saving it to an image file shows the correct png, which makes me think the sprite is pointing to the texture. Any help is greatly appreciated!  ;D

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11175
    • View Profile
    • development blog
    • Email
Re: Sprite from Drawable object not appearing in window
« Reply #1 on: February 04, 2025, 10:47:18 am »
The issue is likely that when you set the texture in the initialization list, the texture has no size and thus the texture rect of the sprite will also be set to no size. Then when you load the texture, you never adjust the texture rect and thus nothing is shown.

The sprite.setTexture call isn't necessary, as you've already set the texture by passing it to the sprite, but what you want to do is call sprite.setTextureRect(IntRect({0, 0}, Vector2i(texture.getSize()))) to match the texture size.

MyDrawable::MyDrawable() : sprite(texture) {
    if (!texture.loadFromFile("image.png")) {
        std::cerr << "Error loading texture!" << std::endl;
    } else {
        sprite.setTextureRect(sf::IntRect({0, 0}, sf::Vector2i(texture.getSize())));
    }
}

Or if you're fine with handling exceptions, you could also do:

MyDrawable::MyDrawable() : texture("image.png"), sprite(texture) {
}
« Last Edit: February 04, 2025, 12:44:51 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq/
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hapax

  • Hero Member
  • *****
  • Posts: 3415
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Sprite from Drawable object not appearing in window
« Reply #2 on: February 04, 2025, 10:59:59 am »
        sprite.setTextureRect(IntRect({0, 0}, Vector2i(texture.getSize())));
 

You can also reset it automatically using:
        sprite.setTexture(texture, true); // note the added "true" here
 

but internally it just does the code that eXpl0it3r posted anyway and doing that manually gives more control in case you might want to use a part of the texture instead of the entire image.

In fact, if you use eXpl0it3r's code, you'll likely need to add "sf::" to the IntRect and the Vector2i ;)



On a separate note, there is no longer any need to use "virtual" keyword when you provide an "override" keyword.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11175
    • View Profile
    • development blog
    • Email
Re: Sprite from Drawable object not appearing in window
« Reply #3 on: February 04, 2025, 12:45:30 pm »
In fact, if you use eXpl0it3r's code, you'll likely need to add "sf::" to the IntRect and the Vector2i ;)
That's what I get for copy-pasting ;D
It's fixed ;)
Official FAQ: https://www.sfml-dev.org/faq/
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

HpHydra

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Sprite from Drawable object not appearing in window
« Reply #4 on: February 04, 2025, 05:14:54 pm »
Thank you both for your help, Problem solved!

P.S. slightly embarrassing that I somehow missed the resetRect parameter on setTexture, ah well, thanks again! :D