c++ - 使用复制构造函数后 SDL 纹理不渲染

标签 c++ class rendering sdl copy-constructor

我正在制作一个使用 SDL 渲染图形的基本程序。我有两个处理渲染的类:

Texture 类(加载并渲染 SDL_textures)

//Texture warpper class
class LTexture
{
private:
    //The actual texture
    SDL_Texture* mTexture;

    //Image demensions
    int mWidth;
    int mHeight;

public:
    //Initializes/Deallocates variables
    LTexture();
    ~LTexture();
    LTexture(const LTexture &rhs);

    //Loads image at specified path
    bool loadFromFile(std::string path);

    //Deallocates texture
    void free();

    //Renders texture at given point
    void render(int x, int y);

    //Gets image dimensions
    int getWidth();
    int getHeight();


};


    LTexture::LTexture()
{
    //Initialize
    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;
}

LTexture::~LTexture()
{
    //Deallocate
    free();
}

LTexture::LTexture(const LTexture &rhs)
{
    mTexture = rhs.mTexture;
    mWidth = rhs.mWidth;
    mHeight = rhs.mHeight;
}

bool LTexture::loadFromFile(std::string path)
{
    //Get rid of preexisting texture
    free();

    //The final texture
    SDL_Texture* newTexture = NULL;

    //Load image at specified path
    SDL_Surface* loadedSurface = IMG_Load(path.c_str());
    if (loadedSurface == NULL)
    {
        printf("Unable to load image %s! SDL_image error: %s\n", path.c_str(), IMG_GetError());
    }
    else
    {
        //Create texture from surface pixels
        newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
        if (newTexture == NULL)
        {
            printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
        }
        else
        {
            //Get image dimensions
            mWidth = loadedSurface->w;
            mHeight = loadedSurface->h;
        }

        //Get rid of old loaded surface
        SDL_FreeSurface(loadedSurface);
    }

    //Return success
    mTexture = newTexture;
    return mTexture != NULL;
}

void LTexture::free()
{
    //Free Texture if it exists
    if (mTexture != NULL)
    {
        SDL_DestroyTexture(mTexture);
        mTexture = NULL;
        mWidth = 0;
        mHeight = 0;
    }
}

void LTexture::render(int x, int y)
{
    //Set rendering space and render to screen
    SDL_Rect renderQuad = { x, y, mWidth, mHeight };
    SDL_RenderCopy(gRenderer, mTexture, NULL, &renderQuad);

    printf("Rendering...\n");

    if (mTexture == NULL)
    {
        printf("No texture loaded!\n");
    }
    else
    {
        printf("Texture loaded! %s\n", mTexture);
    }
}

int LTexture::getWidth()
{
    return mWidth;
}

int LTexture::getHeight()
{
    return mHeight;
}

还有一个 Button 类(这应该可以更轻松地在与按钮状态关联的不同纹理之间切换。每个对象应该在按钮内有 3 个纹理对象)。

声明:

        //Class for buttons and chips
    class Button
    {
    public:
        //Initializes internal variables
        Button();

        //Handles mouse events
        void handleEvent(SDL_Event* e);

        //Render buttons
        void render();

        //Sets top left position
        void setPosition(int x, int y);

        //Gets image dimensions
        void setWidth(int w);
        void setHeight(int h);

        //Set button status
        void setButtonAction(buttonAction action);

        //Get button status
        buttonStatus getButtonStatus();

        //Perform button action !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!FIXME::HAVEN'T DEFINED!!!!!!!!!!!!!!!!!!!!!!!!!!!!1!!
        void activateButton(buttonAction action);

        void setTextures(LTexture out, LTexture over, LTexture down);


    private:
        //Top left position
        SDL_Point mPosition;

        //Currently used global image
        buttonStatus mButtonStatus;

        //What happens if button is pressed
        buttonAction mButtonAction;

        //Width and height
        int mWidth;
        int mHeight;

        //Textures
        LTexture mOut;
        LTexture mOver;
        LTexture mDown;

    };

Button::Button()
{
    mPosition.x = 0;
    mPosition.y = 0;

    mWidth = 0;
    mHeight = 0;

    mButtonStatus = MOUSE_OUT;

}

void Button::setPosition(int x, int y)
{
    mPosition.x = x;
    mPosition.y = y;
}

void Button::handleEvent(SDL_Event* e)
{
    bool mInside = true;

    //If mouse event happened
    if (e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEMOTION)
    {
        //Get mouse position
        int x, y;
        SDL_GetMouseState(&x, &y);

        //Mouse is left of the button
        if (x < mPosition.x)
        {
            mInside = false;
        }
        //Mouse is right of button
        else if (x > mPosition.x + mWidth)
        {
            mInside = false;
        }
        //Mouse is above button
        else if (y < mPosition.y)
        {
            mInside = false;
        }
        //Mouse is below button
        else if (y > mPosition.y + mHeight)
        {
            mInside = false;
        }

        //Logic\\

        //Mouse is outside of button
        if (!mInside)
        {
            mButtonStatus = MOUSE_OUT;
        }
        //Mouse is inside of button
        else
        {
            switch (e->type)
            {
            case SDL_MOUSEMOTION:
                mButtonStatus = MOUSE_OVER;
                break;

            case SDL_MOUSEBUTTONDOWN:
                mButtonStatus = MOUSE_BUTTON_DOWN;
                break;
            }
        }
    }
}

void Button::render()
{
    switch (mButtonStatus)
    {
    case MOUSE_OUT:
        mOut.render(mPosition.x, mPosition.y);
        printf("Out rendered\n");
        break;

    case MOUSE_OVER:
        mOver.render(mPosition.x, mPosition.y);
        printf("Over rendered\n");
        break;

    case MOUSE_BUTTON_DOWN:
        mDown.render(mPosition.x, mPosition.y);
        printf("Down rendered\n");
        break;
    }
}


void Button::setWidth(int w)
{
    mWidth = w;
}

void Button::setHeight(int h)
{
    mHeight = h;
}

void Button::setButtonAction(buttonAction action)
{
    mButtonAction = action;
}

buttonStatus Button::getButtonStatus()
{
    return mButtonStatus;
}

void Button::setTextures(LTexture out, LTexture over, LTexture down)
{
    mOut = out;
    mOver = over;
    mDown = down;
}

不幸的是,当我尝试使用复制构造函数将 SDL_Texture 值从原始纹理传递到按钮私有(private)纹理时,它没有传递任何值,但仍然认为它不是“NULL”

最佳答案

我发现这段代码有两个问题。 第一个是在 LTexture 复制构造函数中,您仅将指针复制到SDL_Texture。这称为浅拷贝。然后,在LTexture 的析构函数中,调用free(),这会删除SDL_Texture。这很糟糕,因为这意味着 LTexture 的任何重复项现在都具有指向已删除纹理的指针,因此它们将不再起作用。这里最好的两个解决方案是使用一个名为 shared_ptr 的 C++11 类来存储纹理,这将防止它被删除,或者实际上创建纹理的拷贝并指向新的纹理一个(深拷贝)。为了进行测试,您可以尝试仅注释掉 free() 中对 SDL_DestroyTexture 的调用。

此外,您忘记实现赋值运算符。目前它的行为就像复制构造函数(因为您所做的只是浅复制),但如果您将其设为深复制,则也必须实现它。

关于c++ - 使用复制构造函数后 SDL 纹理不渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31775283/

相关文章:

c++ - 如何将 QWebEngineView 呈现给打印机?

java - 使用 Swing 渲染放置位置

java - Swing 无法正确渲染我的 JPanel

c++ - 对空字符的必要性感到困惑?

python - 在没有冗余代码/文档字符串的情况下转发/重定向 python 类中的方法/属性的最佳方法?

java - java中的中缀到后缀的转换

c++ - 访问与父类是 friend 的类的私有(private)成员

c++ - 为什么gtest不喜欢我的表情?

c++ - PIN 工具能否检测包含运行其他命令的代码的 bash 脚本?

c++ - 汇编asm x86加解密程序