Home > front end >  Why is my SFML sprite not showing texture?
Why is my SFML sprite not showing texture?

Time:09-03

I'm trying to create a game. I have a class GameObjects that many classes will inherit from. The class GameObject has a draw method that takes the window address to the display. Why does the sprite show up without the texture when displayed like this?

Game Running

EmptySquare.png

This is the texture, more of a placeholder. I was able to load it in other files directly creating the sprite and drawing it. Here is my main.cpp

#include <iostream>
#include "Game.h"

int main()
{
    //window setup
    Game game;

    //Initialize game
    game.start();
    
    return 0;
}

Here is my Game.h

#pragma once

#include "GameObject.h"

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

class Game
{
private:
    //window variables
    int w_width;
    int w_height;

    sf::RenderWindow window;

    sf::Event ev;

    bool isRunning;

    std::vector<GameObject> o_vector;

    
    void initVariables();
    void initWindow();
    void initObjects();
    void drawObjects();
public:
    void start();
    void run();
    void input();
    void update();
    void render();
};

And Game.cpp

#include "Game.h"
#include "GameObject.h"

void Game::start()
{
    this->initVariables();
    this->initWindow();
    this->initObjects();
    this->run();
}

//Initializations
void Game::initVariables()
{
    isRunning = true;
    
    //window variables
    w_width = 1280;
    w_height = 720;
}

void Game::drawObjects()
{
    for (int o_count = 0; o_count < o_vector.size(); o_count  )
    {
        o_vector.at(o_count).draw(window);
    }

}

void Game::initWindow()
{
    //window creation
    window.create(sf::VideoMode(w_width, w_height), "The Dungeon Crawler", sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize);
}

void Game::initObjects()
{
    GameObject baseObject;
    o_vector.push_back(baseObject);

}

void Game::run()
{
    while (isRunning)
    {
        input();
        update();
        render();
    }
}

void Game::input()
{
    while (window.pollEvent(ev))
    {
        switch (ev.type)
        {
        case sf::Event::Closed:
            window.close();
            break;
        case sf::Event::KeyPressed:
            switch (ev.key.code)
            {
            case sf::Keyboard::Escape:
                window.close();
                break;
            case sf::Keyboard::A:
                break;
            }
        }
    }
}

void Game::update()
{
}

void Game::render()
{
    window.clear(sf::Color(0, 0, 128));

    drawObjects();

    window.display();
}

Here is GameObject.h

#pragma once

#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>


class GameObject
{
private:
    std::string name;

    std::vector<int> o_position;
    std::vector<int> o_size;

    std::string t_path;
    sf::Sprite o_sprite;
    sf::Texture o_texture;

    void initVariables();
public:
    //Constructors & Destructors
    GameObject();
    ~GameObject();


    //Getters
    std::vector<int> getPos();
    std::vector<int> getSize();

    sf::Sprite getSprite();

    //Setters
    void setPos(std::vector<int>pos_in);
    void setSize(std::vector<int> size_in);

    //Graphics
    void draw(sf::RenderWindow &displayWindow);
};

And GameObject.cpp

#include "GameObject.h"

GameObject::GameObject()
{
    initVariables();
}

GameObject::~GameObject()
{

}

void GameObject::initVariables()
{
    o_position = { 0,0 };
    o_size = { 64,64 };

    t_path = "Resources/EmptySquare.png";

    if (!o_texture.loadFromFile(t_path))
    {
        std::cout << "Failed to load" << std::endl;
        return;
    }
    o_sprite.setTexture(o_texture);
}

std::vector<int> GameObject::getPos()
{
    return o_position;
}

std::vector<int> GameObject::getSize()
{
    return o_size;
}

sf::Sprite GameObject::getSprite()
{
    return o_sprite;
}

void GameObject::setPos(std::vector<int> pos_in)
{
    o_position = pos_in;
}

void GameObject::setSize(std::vector<int> size_in)
{
    o_size = size_in;
}

void GameObject::draw(sf::RenderWindow &displayWindow)
{
    displayWindow.draw(o_sprite);
}

Thank you for any help!

CodePudding user response:

the problem is this line in Game::initObjects()

GameObject baseObject;
o_vector.push_back(baseObject);
  • you creata a copy of GameObject.
  • so it will make a copy of o_sprite.
  • the o_sprite copies the texture pointer.
  • after this function ends, the texture pointer is no longer valid.

sf::Sprite has the member const Texture* m_texture; and when calling sf::Sprite::setTexture(const Texture& texture) this member m_texture will in fact point to the texture. That texture will be destructed after initObjects() ends, and your element at position 0 will have a o_sprite.m_texture that points to this destructed object. sprite now loaded in the program

CodePudding user response:

Another way would be for you to allocate game object on the heap and store a pointer to it in the vector. This way you will avoid the cost of copying.

To make these changes, declare baseObject as private member of Game class and in initObjects method allocate it on the heap.

class Game
{
private:
    GameObject *baseObject;
    std::vector<GameObject *> o_vector;
};
void Game::initObjects()
{
    baseObject = new GameObject;
    o_vector.push_back(baseObject);
}
void Game::drawObjects()
{
    for (int o_count = 0; o_count < o_vector.size(); o_count  )
    {
        o_vector.at(o_count)->draw(window); // use -> operator to call draw
    }
}

PS: Instead of raw pointer, you can also use C 11 smart pointer.

  • Related