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: http://imgur.com/zioTz5i

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\$
2
\$\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.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.