为什么我的渲染器没有在 SDL2 中初始化?

Why isn't my renderer initialising in SDL2?

抱歉代码太多,我不喜欢将所有内容都放在一个文件中,您需要查看所有文件。无论如何,问题是 Window class 中的 init 函数(在 SDL.cpp 中初始化并在 SDL.hpp 中声明),渲染器不工作?当然,这意味着图像和纹理也不会加载,但我认为这都是因为渲染器失败。你能弄清楚它为什么这样做并帮助我吗?

如果我没有解释清楚,请告诉我,谢谢。

Main.cpp

#include <iostream>
#include <SDL.h>
#include "SDL.hpp"

int main(int argc, char* args[])
{
    Window window("SDL window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1080, 720, false);

    //Start up SDL and create window
    if (window.init()) 
    {
        if (window.loadMedia())
        {
            bool quit = false;
            SDL_Event e;
            window.image = window.load_surface("Hello_World.bmp");
            while (window.running)
            {
                while (SDL_PollEvent(&e) != 0)
                {
                    //User requests quit
                    if (e.type == SDL_QUIT)// if event SDL_QUIT is added the poll event
                    {
                        window.running = false;// will shutdown the game loop running everything and close the program.
                    }
                }
                //Clear screen
                SDL_RenderClear(window.gRenderer);

                //Render texture to screen
                SDL_RenderCopy(window.gRenderer, window.gTexture, NULL, NULL);

                //Update screen
                SDL_RenderPresent(window.gRenderer);

                SDL_UpdateWindowSurface(window.gWindow);
            }
        }
    }

    window.close();

    return 0;
}

SDL.hpp

#include <SDL.h>

class Window {
public:
    Window(const char* title_, int xpos_, int ypos_, int width_, int height_, bool fullscreen_);
    //Starts up SDL and creates window
    bool init();

    //Loads media
    bool loadMedia();

    //loads an image/texture(to the) surface
    SDL_Surface* load_surface(std::string path);
    SDL_Texture* load_texture(std::string path);

    // renderer
    SDL_Renderer* renderer = nullptr;

    //Frees media and shuts down SDL
    void close();

    //The window we'll be rendering to
    SDL_Window* gWindow = nullptr;

    //The surface contained by the window
    SDL_Surface* gScreenSurface = nullptr;

    //The window renderer
    SDL_Renderer* gRenderer = NULL;

    //Current displayed texture
    SDL_Texture* gTexture = NULL;
    
    bool running = true;
    SDL_Surface* image = nullptr;
    SDL_Surface* image1 = nullptr;
    SDL_Surface* image2 = nullptr;
    int imageNum = 1;
private:
    int width;
    int height;
    int xpos;
    int ypos;
    const char* title;
    bool fullscreen;
};

SDL.cpp

#include <iostream>
#include "SDL.hpp"
#include <SDL.h>

Window::Window(const char* title_, int xpos_, int ypos_, int width_, int height_, bool fullscreen_) {
    title = title_;
    xpos = xpos_;
    ypos = ypos_;
    width = width_;
    height = height_;
    fullscreen = fullscreen_;
}
bool Window::init()
{
    //Initialization flag
    bool success = true;
    int flags = 0;
    //Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "SDL could not initialize! SDL_Error: %s\n" << SDL_GetError() << std::endl;
        success = false;
    }
    else
    {
        if (fullscreen) {
            flags = SDL_WINDOW_FULLSCREEN;
        }
        //Create window
        gWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
        if (gWindow == NULL)
        {
            std::cout << "Window could not be created! SDL_Error: %s\n" << SDL_GetError() << std::endl;
            success = false;
        }
        else
        {
            renderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
            if (gRenderer == NULL)
            {
                std::cout << "renderer failed to init" << std::endl;
            }
            //Initialize renderer color
            SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );                
        }
    }

    return success;
}
SDL_Surface* Window::load_surface(std::string path)
{
    //The final optimized image
    SDL_Surface* optimizedSurface = nullptr;

    SDL_Surface* loadSurface = SDL_LoadBMP(path.c_str());
    if (loadSurface == NULL)
    {
        std::cout << "Unable to load image %s! SDL Error: %s\n" << path.c_str() << SDL_GetError() << std::endl;
    }
    else
    {
        //Convert surface to screen format
        optimizedSurface = SDL_ConvertSurface(loadSurface, gScreenSurface->format, 0);
        if (optimizedSurface == NULL)
        {
            std::cout << "Unable to optimize image %s! SDL Error: %s\n" << path.c_str() << SDL_GetError() << std::endl;
        }

        //Get rid of old loaded surface
        SDL_FreeSurface(loadSurface);
    }
    return optimizedSurface;
}

SDL_Texture* Window::load_texture(std::string path)
{
    //The final texture
    SDL_Texture* newTexture = NULL;

    //Load image at specified path
    SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
    if (loadedSurface == NULL)
    {
        std::cout << "Unable to load image %s! SDL_image Error: %s\n" << path.c_str() << std::endl;
    }
    else
    {
        //Create texture from surface pixels
        newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
        if (newTexture == NULL)
        {
            std::cout << "Unable to create texture from %s! SDL Error: %s\n" << path.c_str() << std::endl;
        }

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

    return newTexture;
}

bool Window::loadMedia()
{
    bool success = true;
    gTexture = load_texture("Hello_World.bmp");
    if (gTexture == NULL)
    {
        std::cout << "Failed to load texture image!\n" << std::endl;
        success = false;
    }
    return success;
}

void Window::close()
{
    //Free loaded image
    SDL_DestroyTexture(gTexture);
    gTexture = NULL;

    //Destroy window    
    SDL_DestroyRenderer(gRenderer);
    SDL_DestroyWindow(gWindow);
    gWindow = NULL;
    gRenderer = NULL;

    //Quit SDL subsystems
    SDL_Quit();
}
  1. SDL.hpp 包含两个 SDL_Renderer* 成员:renderergRenderer。删除前者并更新 SDL.cpp 中的这一行以使用后者:

    gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
    
  2. 在函数 Window::load_surface(..) 中有一个对 SDL_ConvertSurface 的调用,它使用 gScreenSurface 仍然是一个空指针。首先,从 window:

    获取曲面
    gScreenSurface = SDL_GetWindowSurface(gWindow);
    
  3. 代码现在应该 运行,但位图可能会在 window 中闪烁或根本不出现。这是因为 main 函数中的渲染循环试图尽快更新 window 。要显示稳定的图像,让程序在 SDL_RenderPresent 调用后立即等待按键,或者让线程在那里休眠。

为简洁起见,省略了代码片段中的所有错误检查。