为什么我的渲染器没有在 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();
}
SDL.hpp 包含两个 SDL_Renderer*
成员:renderer
和 gRenderer
。删除前者并更新 SDL.cpp 中的这一行以使用后者:
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
在函数 Window::load_surface(..)
中有一个对 SDL_ConvertSurface
的调用,它使用 gScreenSurface
仍然是一个空指针。首先,从 window:
获取曲面
gScreenSurface = SDL_GetWindowSurface(gWindow);
代码现在应该 运行,但位图可能会在 window 中闪烁或根本不出现。这是因为 main
函数中的渲染循环试图尽快更新 window 。要显示稳定的图像,让程序在 SDL_RenderPresent
调用后立即等待按键,或者让线程在那里休眠。
为简洁起见,省略了代码片段中的所有错误检查。
抱歉代码太多,我不喜欢将所有内容都放在一个文件中,您需要查看所有文件。无论如何,问题是 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();
}
SDL.hpp 包含两个
SDL_Renderer*
成员:renderer
和gRenderer
。删除前者并更新 SDL.cpp 中的这一行以使用后者:gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
在函数
获取曲面Window::load_surface(..)
中有一个对SDL_ConvertSurface
的调用,它使用gScreenSurface
仍然是一个空指针。首先,从 window:gScreenSurface = SDL_GetWindowSurface(gWindow);
代码现在应该 运行,但位图可能会在 window 中闪烁或根本不出现。这是因为
main
函数中的渲染循环试图尽快更新 window 。要显示稳定的图像,让程序在SDL_RenderPresent
调用后立即等待按键,或者让线程在那里休眠。
为简洁起见,省略了代码片段中的所有错误检查。