首页 > 解决方案 > SDL2 无法打开任何 BMP 文件

问题描述

我正在尝试按照lazyfoo 的教程使用SDL2 来习惯它,但即使是最基本的大多数程序也无法正常工作。我可以打开一个没有图像的基本空白窗口并保持打开状态,但是一旦我尝试在窗口中打开 BMP 文件,它就会变得很奇怪并且不再起作用。我的代码,最初没有显示错误:

#include <SDL2/SDL.h>
#include <cstdio>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

SDL_Window *newWindow = nullptr;
SDL_Surface *loadedImage = nullptr;
SDL_Surface *screenSurface = nullptr;
bool quit = false;
SDL_Event event;

bool initWindow() {
    bool state = true;

    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::puts("Error init");
        state = false;
    }
    else
    {
        newWindow = SDL_CreateWindow("Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                     SCREEN_WIDTH,
                                     SCREEN_HEIGHT, SDL_WINDOWEVENT_SHOWN);

        if (nullptr == newWindow)
        {
            std::puts("Error window");
            state = false;
        }
        else
        {
            screenSurface = SDL_GetWindowSurface(newWindow);
        }
    }
    return state;
}

bool loadMedia() {
    bool success = true;

    loadedImage = SDL_LoadBMP("LAND3.BMP");

    if (loadedImage == nullptr)
    {
        printf("Error image %s \n", SDL_GetError());
        success = false;
    }

    return success;
}

void closeWindow() {
    SDL_FreeSurface(loadedImage);
    loadedImage = nullptr;

    SDL_DestroyWindow(newWindow);
    newWindow = nullptr;

    SDL_Quit();
}

int main(int argc, char *args[]) {

    if (!initWindow())
    {
        std::puts("Error init main");
    }
    else
    {
        if (!loadMedia())
        {
            std::puts("Error image main");
        }
        else
        {
            while (!quit)
            {
                if (event.type == SDL_QUIT)
                {
                    quit = true;
                }
                else
                {
                    SDL_BlitSurface(loadedImage, nullptr, screenSurface, nullptr);
                    SDL_UpdateWindowSurface(newWindow);
                }
            }
        }
    }

    closeWindow();

    return 0;
}

运行这个程序时,我没有收到任何错误,但 UI 开始表现得很疯狂;分辨率变得非常小(比我设置的 480p 小得多),所有窗口都会调整大小,并且会持续很短的时间。如果我while(!quit)用 a 替换循环SDL_Delay(1000),则此行为的持续时间大约与延迟一样长。

最初我怀疑我第一次使用的文件已损坏(我刚刚重命名了现有图片),但后来我下载了一个示例 BMP 文件,但没有任何改变。

使用调试器时loadMedia(),无论我使用哪个文件,都无法加载该文件。我正在使用 MinGW 和 cLion。

可能是什么问题?

标签: c++sdl-2

解决方案


该常量SDL_WINDOWEVENT_SHOWN不是函数的有效标志SDL_CreateWindow。该常量不是作为标志,而是作为事件 ID。您可能打算改用常量SDL_WINDOW_SHOWN

该常量SDL_WINDOWEVENT_SHOWN恰好与SDL_WINDOW_FULLSCREEN(两者都有 value 1)具有相同的值。因此,您不正确的函数调用

newWindow = SDL_CreateWindow("Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                     SCREEN_WIDTH,
                                     SCREEN_HEIGHT, SDL_WINDOWEVENT_SHOWN);

相当于:

newWindow = SDL_CreateWindow("Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                                     SCREEN_WIDTH,
                                     SCREEN_HEIGHT, SDL_WINDOW_FULLSCREEN);

换句话说,您无意中要求 SDL 在 640*480全屏模式下创建窗口。这可能是您的桌面被调整大小的原因。

找不到该文件的原因可能是因为该文件不在您程序的当前工作目录中。您可以确保文件位于该目录中,也可以使用文件的绝对路径,例如"C:\\Users\\MyUsername\\Desktop\\LAND3.BMP".

我怀疑您无法使用任务管理器杀死您的应用程序的问题是 SDL 的错。这可能是 Microsoft Windows 的设计缺陷。请参阅此链接,了解如何使挂起的全屏应用程序更易于访问任务管理器。


推荐阅读