簡體   English   中英

SFML 對子類的繪制調用繪制為白色方塊

[英]SFML draw call to subclass draws as white square

我正在做一個游戲項目,發現自己陷入了以下問題:

我有一個名為Game : public sf::Drawable ,我用來(除其他外)繪制游戲中的所有內容。 Game包含一個名為Player : public Entity的類,它又是Entity : public sf::Drawable的子類。


這些類略有簡化,但受影響的功能是相同的:

實體

class Entity : public sf::Drawable
{
    private:
        sf::Sprite eSprite;
        sf::Texture eTex;
        std::string texpath;
    public:
        virtual Entity(std::string texpath, sf::IntRect intrect){
            this->texpath = texpath;
            eTex.loadFromFile(texpath, intrect);
            eSprite.setTexture(eTex); }
        virtual ~Entity(){}
        virtual void draw(sf::RenderTarget target, sf::RenderStates states)const{
                target.draw(this->eSprite);}
    //Lots of other functions
}

播放器

class Player : public Entity¨
    {
    public:
        ~Player(){}
        Player(std::string texpath, sf::IntRect spriteintrect)
            :Entity(texpath, spriteintrect){}
        void draw(sf::RenderTarget target, sf::RenderStates states){
            Entity::draw(target, states); }
    }

游戲

#define PLAYER_START "../filepath/image.png", 
                          sf::IntRect{0,0,40,60,}, sf::Vector2f(320.0f, 200.0f) //Ease of access

   class Game : public sf::Drawable
{
private:
    Player player;
public:
    Game() { player = Player(PLAYER_START); };
    ~Game() {};
    void draw(sf::RenderTarget &target, sf::RenderStates states)const { target.draw(player); }

};

為了使問題易於理解,我創建了以下代碼示例:

int main(){
    sf::RenderWindow window(sf::VideoMode(640, 480), "Game Test");
    sf::Event event = sf::Event{};
    Game game;

    while (window.isOpen())
    {
        while (window.pollEvent(event))
            if (event.type == sf::Event::Closed) 
                window.close();
        window.clear();
        window.draw(game); 
        window.display();
    }
}

此代碼生成一個白色方塊。

我試過了:

  • Game之外創建一個Player並調用window.draw(player); 在上面。 這有效。
  • 通過賦值運算符和繪圖創建一個新的Player 這有效。
  • 通過復制構造函數和繪圖創建一個新的Player 這有效。
  • Player插入到Game類中並繪制它。 不起作用,這是我用上面的代碼說明的

我意識到這個問題可以(可能)通過將sf::Spritesf::TexturePlayer類來解決,但由於我想最終從 Entity 基類派生CoinEnemy ,我更願意解決問題原樣。*

感謝您的幫助/Lore

sf::Sprite對象存儲指向紋理的指針。

當您為基類設置player = Player() ,將調用復制賦值運算符 - 默認情況下由編譯器生成。 它將所有成員變量一一復制。

執行該復制分配后:

entity1 = entity2;

我們有:

entity1.eSprite = entity2.eSprite; // shallow copy
entity1.eTex = entity2.eTex;

和關鍵點 - entity1.eSprite指向什么紋理? 它是entity2.eTex 而不幸的是你,ENTITY2你的情況暫時的,所以你在SFML懸擺指針紋理里面的精靈......常見的錯誤和它的官方參考描述SFML

您成功加載了一個紋理,正確構建了一個精靈,然后……您現在在屏幕上看到的只是一個白色方塊。 發生了什么?

這是一個常見的錯誤。 當您設置精靈的紋理時,它在內部所做的只是存儲一個指向紋理實例的指針。 因此,如果紋理被破壞或移動到內存中的其他地方,精靈最終會得到一個無效的紋理指針。

解決方案,添加復制賦值運算符,為精靈正確設置紋理,作為deep-copy

Entity& operator=(const Entity& theOther)  {
    if (this != &theOther) {
        this->eTex = theOther.eTex;
        this->eSprite.setTexture(this->eTex); // the most imporant line in this answer
    }
    return *this;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM