0
\$\begingroup\$

I am trying to use spritesheets in SFML. My Player class inherits from the Creature class which inherits from the Entity class. I only see a white square when I render the player. However, this is not the case when I create the sprite and render it in the same function. It does not work if I return a copy or even a reference or a pointer of the sprite. So, I tried constructing my sprite in the constructor rather than the init() method. It still does not work when I return the sprite for drawing via the draw() method in entity.cpp. I do not want to load the sprite from the spritesheet in the draw method as that would be fairly inefficient. Please help.

spritehseet.png: https://i.sstatic.net/H9JzO.jpg

main.cpp:

bool init() {
    /*Code to determine if a player should be added to entities and creatures vectors*/
    case 'P':
                player = new Player(i*64, y*64, 64, 64, sf::IntRect(0, 0, 64, 64), "spritesheet.png", &entities);
                entities.push_back(player);
                creatures.push_back(player);
                break;
 /*more code for quitting and error reporting*/
}


int main() { // vertical sync works well only in full screen mode

    sf::RenderWindow window(sf::VideoMode(0, 0), "My First SFML Game", sf::Style::Fullscreen);
    int frames = 0;
    window.setVerticalSyncEnabled(true);

if(!init()) {
    std::cout << "Could not initialize\n";
    return 1;
}

sf::Clock clock, frameClock;

/*keyboard and event polling code here*/

    if(frameClock.getElapsedTime().asSeconds() >= 1/FPS) {
        update();
        draw(window);
        window.display();
        window.clear();
        frames++;
        frameClock.restart();
    }

    if(clock.getElapsedTime().asSeconds() >= 1) {
        std::cout << frames << " frames per second\n";
        clock.restart();
        frames = 0;
    }
}
    std::cout << "Quitting\n";
    quit();
}


void quit() {
    std::vector<Entity*>::iterator it;
    for(it = entities.begin(); it != entities.end(); it++) {
        delete *it;
        *it = nullptr;
    }
    entities.clear();
    player = nullptr;
    std::vector<Creature*>::iterator it2;
    for(it2 = creatures.begin(); it2 != creatures.end(); it2++) {
        *it2 = nullptr;
    }
}

void update() {
    std::vector<Creature*>::iterator it;
    for(it = creatures.begin(); it != creatures.end(); it++) {
        Creature* creature = *it;
        creature->update();
    }
}

void draw(sf::RenderWindow& window) {
    std::vector<Entity*>::iterator it;
    for(it = entities.begin(); it != entities.end(); it++) {
        Entity* entity = *it;
        window.draw(entity->draw());
    }
}

entity.h:

#ifndef ENTITY_H
#define ENTITY_H

#include <SFML/Graphics.hpp>

#include <string>

class Entity {
private:
    int _x, _y, _width, _height;
    sf::Sprite _sprite;
public:
    Entity(int x, int y, int width, int height, sf::IntRect rect, std::string path);

int getX() { return _x; }
int getY() { return _y; }
int getWidth() { return _width; }
int getHeight() { return _height; }

void setX(int x) { _x = x; }
void setY(int y) { _y = y; }
void setWidth(int width) { _width = width; }
void setHeight(int height) { _height = height; }

sf::Sprite draw();
};

#endif // ENTITY_H

entity.cpp:

#include <entity.h>

#include <string>
#include <iostream>

#include <SFML/Graphics.hpp>

Entity::Entity(int x, int y, int width, int height, sf::IntRect rect, std::string path) {
_x = x;
_y = y;
_width = width;
_height = height;
sf::Texture texture;
if(!texture.loadFromFile(path, rect)) std::cout << "Could not load intrect " << rect.left << ", "
                                                                             << rect.top << ", "
                                                                             << rect.width << ", "
                                                                             << rect.height << " from" << path;
else std::cout << "loaded texture\n";
_sprite.setTexture(texture);
}

sf::Sprite Entity::draw() {
_sprite.setPosition(sf::Vector2f(_x, _y));
return _sprite;
}

The rest of the constructors don't do anything with the sprite.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

See this link: https://www.sfml-dev.org/tutorials/2.4/graphics-sprite.php

You're loading in your sf::texture to a variable local to the constructor. When the code block for the constructor has finished running, this variable goes out of scope. When this happens, your sf::texture is destroyed, which causes the white square. You need to store the texture in a way that won't let it go out of scope, such as allocating it to the heap.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .