SDL UpdateWindowSurface() returns -1 如果从 class 调用(在单独的文件中)

SDL UpdateWindowSurface() returns -1 if called from a class (in separate file)

今天我开始了 C++/SDL2 Snake 克隆,我一直在寻找使我的代码更整洁的方法,尤其是 classes。我试图将所有用于 window/display 的 SDL 代码放在 class 中。当我 运行 代码时, window 立即关闭 。根据我在 display.cpp 中设置的错误测试,它还通过控制台告诉我 SDL_UpdateWindowSurface() (在 display.update() 中)总是返回 -1。当我这样重新排列我的代码时,为什么会发生这种情况?

使用此代码,我在 main() 中加载图像并通过我的 class' 函数 applySurface() 显示它。这个想法是让 classes/objects 用于游戏的 grid/board、蛇等,每个都为自己的图像调用 applySurface()。如果这完全是个坏主意,请随时告诉我。

main.cpp:

#include <SDL.h>
#include "display.h"

SDL_Event event;
SDL_Surface* image = nullptr;

int main(int argc, char* args[])
{
    Display display;
    display.loadImage("image.bmp");

    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
        return false;

    bool quit = false;

    while (!quit)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                quit = true;
        }

        display.applySurface(0, 0, image, display.windowSurface);
        display.update();
    }

    SDL_FreeSurface(image);
    SDL_Quit();
    return 0;
}

display.h:

#pragma once
#include <SDL.h>
#include <string>
#include <iostream>

class Display
{
public:
    SDL_Window* window;
    SDL_Surface* windowSurface;

    Display();
    SDL_Surface *loadImage(std::string fileName);
    void applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = nullptr);
    void update();
    ~Display();
private:
    const int WINDOW_WIDTH = 612;
    const int WINDOW_HEIGHT = 632;
    const int SCREEN_BPP = 2;
};

display.cpp:

#pragma once
#include "display.h"

Display::Display()
{
    window = SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);

    if (window == NULL)
        std::cout << "Error: SDL_CreateWindow failed." << std::endl;

    windowSurface = SDL_GetWindowSurface(window);
}

SDL_Surface* Display::loadImage(std::string fileName)
{
    SDL_Surface* loadedImage = NULL;
    SDL_Surface* optimizedImage = NULL;

    loadedImage = SDL_LoadBMP(fileName.c_str());

    if (loadedImage != NULL)
    {
        optimizedImage = SDL_ConvertSurface(loadedImage, windowSurface->format, 0);

        SDL_FreeSurface(loadedImage);

        if (optimizedImage != NULL)
            SDL_SetColorKey(optimizedImage, SDL_TRUE, SDL_MapRGB(optimizedImage->format, 255, 255, 255));
    }

    return optimizedImage;
}


void Display::applySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip)
{
    SDL_Rect offset;

    offset.x = x;
    offset.y = y;

    SDL_BlitSurface(source, clip, destination, &offset);
}

void Display::update()
{
    if (SDL_UpdateWindowSurface(window) == -1)
        std::cout << "Error: SDL_UpdateWindowSurface() failed." << std::endl;
}

Display::~Display()
{
    SDL_FreeSurface(windowSurface);
    windowSurface = NULL;

    SDL_DestroyWindow(window);
    window = NULL;
}

这是对 classes 构建代码的有效使用。 SDL_Init 需要在任何其他 SDL 函数之前出现,这意味着您最好将 SDL_Init 移动到 main 的顶部或将其添加到显示构造函数。如果将它添加到显示构造函数的开头,这意味着您一次只能有一个显示 class 对象 运行,在这种情况下可能没问题。