SFML Sprite white square

2019-09-17 17:12发布

问题:

I have asked a question about SFML smooth movement yesterday... and that problem was solved, but this time the sprite that im using is showing up as a white square.

I have tried to send the sprite to drawship function as reference but since i am using that function on main.cppi am not able to do what is told on this answer. So Im wondering how I can fix this problem.

main.cpp

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "Spaceship.hpp"
#include <vector>

#include "ResourcePath.hpp"

int main(int, char const**)
{

    // Create the main window
    sf::RenderWindow window(sf::VideoMode(800, 600), "SpaceShuttle");
    window.setFramerateLimit(30);
    // Call to non-static member function without an object argument
    // Set the Icon
    sf::Image icon;
    if (!icon.loadFromFile(resourcePath() + "space-shuttle.png")) {
        return EXIT_FAILURE;
    }
    window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());

    // Load a sprite to display
    sf::Texture texture;
    if (!texture.loadFromFile(resourcePath() + "bg.png")) {
        return EXIT_FAILURE;
    }
    sf::Sprite sprite(texture);

    // Create a graphical text to display
    sf::Font font;
    if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
        return EXIT_FAILURE;
    }
    sf::Text text("SpaceShuttle K1LLM33K", font, 50);
    text.setFillColor(sf::Color::White);
    text.setPosition(100.0, 130.0);


    // Load a music to play
   /* sf::Music music; if (!music.openFromFile(resourcePath() + "nice_music.ogg")) { return EXIT_FAILURE; } 
    // Play the music
    music.play();
    */

    Spaceship spaceship(window);
    sf::Clock sf_clock;


    // Start the game loop
    while (window.isOpen()) {
        // Get time elapsed since last frame
        float dt = sf_clock.restart().asSeconds();

        // Process events
        sf::Event event;
        while (window.pollEvent(event)) {
            // Close window: exit
            if (event.type == sf::Event::Closed) {
                window.close();
            }

            // Escape pressed: exit
            if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
                window.close();
            }


        }
        //move spaceship
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { spaceship.moveship(dt, 'l'); }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { spaceship.moveship(dt, 'r'); }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) { spaceship.moveship(dt, 'u'); }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { spaceship.moveship(dt, 'd'); }
        // Clear screen
        window.clear();

        // Draw the sprite(s)
        window.draw(sprite);
        //
        // To draw the Spaceship
        //
        spaceship.drawsprite(window);

        // Draw the string(s)
        window.draw(text);

        // Update the window
        window.display();
    }

    return EXIT_SUCCESS;
}

spaceship.cpp

#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"
#include "Spaceship.hpp"

Spaceship::Spaceship(sf::RenderWindow& game_window){
    auto surface = game_window.getSize();
    ss_x = ss_y = 0.5f;
    ss_speed_x = 250.f / surface.x;
    ss_speed_y = 250.f / surface.y;
    ss_width = 128;
    ss_height = 128;
    ss_radius = ss_width/2;

    sf::Texture ship;
    if (!ship.loadFromFile(resourcePath() + "space-shuttle-64.png")) {
        return EXIT_FAILURE;
    }

    ss_sprite = sf::Sprite(ship);
    ss_sprite.setOrigin(ss_width / 2, ss_height / 2);

}


void Spaceship::drawsprite(sf::RenderWindow& game_window){
    auto size = game_window.getSize();
    ss_sprite.setPosition(ss_x * size.x, ss_y * size.y);
    game_window.draw(ss_sprite);
}

void Spaceship::moveship(float dt, char move){
    switch (move) {
        case 'l': ss_x -= dt * ss_speed_x; break;
        case 'r': ss_x += dt * ss_speed_x; break;
        case 'u': ss_y -= dt * ss_speed_y; break;
        case 'd': ss_y += dt * ss_speed_y; break;
    }
}

Spaceship::~Spaceship(){}

spaceship.hpp

#ifndef Spaceship_hpp
#define Spaceship_hpp
#include <iostream>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <stdio.h>

using namespace std;

class Spaceship {
public:
    Spaceship();
    Spaceship(sf::RenderWindow&);
    ~Spaceship();
    void moveship(float, char);
    void drawsprite(sf::RenderWindow&);
private:
    float ss_x, ss_y;
    float ss_speed_x, ss_speed_y;
    int ss_width, ss_height, ss_radius;
    sf::Sprite ss_sprite;

};

#endif /* Spaceship_hpp */

回答1:

According to the docs, "The texture must exist as long as the sprite uses it. Indeed, the sprite doesn't store its own copy of the texture", so just moving the sf::Texture from the constructor to a member of Spaceship should fix it.

class Spaceship {
    // Some stuff
    sf::Texture ss_ship_texture;
};

Spaceship::Spaceship(const sf::RenderWindow& window) {
    // Some stuff
    ss_ship_texture.loadFromFile("path/to/ship/image");
    ss_ship.setTexture(ss_ship_texture);
}


回答2:

A white square rather than your texture usually hints at the texture not being initialized/created or it being destroyed/invalid.

In your case, you're creating a texture object in your Spaceship constructor, which won't be valid once the constructor is done. Note that sf::Sprite just receives/stores a reference (pointer) to your texture rather than a copy of the actual texture.

You'll have to store it outside, e.g. as part of some resource manager class, or simply pass it to your Spaceship constructor.



标签: c++ sprite sfml