上一课我们讲解了关于如何用SDL显示一个BMP的图片,其实就是涉及SDL_Window,SDL_Surface,SDL_Renderer,SDL_Texture,如果在SDL上面显示几个图片呢,也很简单,也就是用多个SDL_Texture绘制在一个SDL_Renderer上,在指定位置以及大小就可以了,下面看一下代码的实现:
讲解:
const int SCREEN_WIDTH = 640;//Window窗口宽度
const int SCREEN_HEIGHT = 480;//Window窗口的高度
//SDL_window窗口的销毁
void Clesson03::cleanup(SDL_Window* window)
{
SDL_DestroyWindow(window);
//SDL_QUIT();
}
//销毁Renderer,window,Texure,原作者写的这个函数比这个要好,这里仅仅是为了实现功能。
void Clesson03::cleanup(SDL_Texture* background, SDL_Texture* image, SDL_Renderer* renderer, SDL_Window* window)
{
if(background)
{
SDL_DestroyTexture(background);
}
if(image)
{
SDL_DestroyTexture(image);
}
if(renderer)
{
SDL_DestroyRenderer(renderer);
}
if(window)
{
SDL_DestroyWindow(window);
}
}
/*
这个就是标准的C++输出功能,SDL_GetError()获取错误码
*/
void Clesson03::logSDLError(std::ostream &os, const std::string &msg){
os << msg << " error: " << SDL_GetError() << std::endl;
}
/*
* LOAD一个BMP文件,并且返回一个SDL_Texture
* @param file BMP文件
* @param ren 需要渲染的renderer
* @return 一个SDL_Texture指针或者NULL.
*/
SDL_Texture* Clesson03::loadTexture(const std::string &file, SDL_Renderer *ren){
SDL_Texture *texture = nullptr;
//Load the image
SDL_Surface *loadedImage = SDL_LoadBMP(file.c_str());
//If the loading went ok, convert to texture and return the texture
if (loadedImage != nullptr){
texture = SDL_CreateTextureFromSurface(ren, loadedImage);
SDL_FreeSurface(loadedImage);
//Make sure converting went ok too
if (texture == nullptr){
logSDLError(std::cout, "CreateTextureFromSurface");
}
}
else {
logSDLError(std::cout, "LoadBMP");
}
return texture;
}
/*
* 绘制Texure在Renderer指定的位置。
* the texture's width and height
* @param tex 需要在Renderer绘制的Texture;
* @param ren Texture绘制的Renderer
* @param x X位置
* @param y Y位置
感觉写的意思很别扭,文笔不是很好(只可意会,不可言传)
*/
void Clesson03::renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){
//Setup the destination rectangle to be at the position we want
SDL_Rect dst;
dst.x = x;
dst.y = y;
//Query the texture to get its width and height to use
SDL_QueryTexture(tex, NULL, NULL, &dst.w, &dst.h);
SDL_RenderCopy(ren, tex, NULL, &dst);
}
int Clesson03::Run(int argc, char** argv){
//SDL的初始化
if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
logSDLError(std::cout, "SDL_Init");
return 1;
}
//创建SDL_Window
SDL_Window *window = SDL_CreateWindow("OAD工作室-多个BMP显示", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == nullptr){
logSDLError(std::cout, "CreateWindow");
SDL_Quit();
return 1;
}
//创建SDL_Renderer
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == nullptr){
logSDLError(std::cout, "CreateRenderer");
cleanup(window);
SDL_Quit();
return 1;
}
//创建两个Texture,一个背景,一个前景
const std::string resPath(argv[1]);
SDL_Texture *background = loadTexture(resPath + "background.bmp", renderer);
SDL_Texture *image = loadTexture(resPath + "image.bmp", renderer);
//Make sure they both loaded ok
if (background == nullptr || image == nullptr){
cleanup(background, image, renderer, window);
SDL_Quit();
return 1;
}
//Clear SDL_Window,准备开始绘制
SDL_RenderClear(renderer);
//这个函数就是获取Texture的信息,如果不能理解(你可以认为是BMP的一些信息,其实这里已经没有sureface什么事了)
int bW, bH;
SDL_QueryTexture(background, NULL, NULL, &bW, &bH);
//在renderer上绘制4个图,这个算法肯定是最笨,就简单的,知道怎么回事就可以了,必定就是一个Demo
renderTexture(background, renderer, 0, 0);
renderTexture(background, renderer, bW, 0);
renderTexture(background, renderer, 0, bH);
renderTexture(background, renderer, bW, bH);
//这里绘制前景在中间显示,代码很简单。
int iW, iH;
SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
int x = SCREEN_WIDTH / 2 - iW / 2;
int y = SCREEN_HEIGHT / 2 - iH / 2;
renderTexture(image, renderer, x, y);
//更新一下renderer
SDL_RenderPresent(renderer);
bool bRun = true;//程序是否允许
SDL_Event AppEven;//SDL事件
while (bRun) {
if(SDL_WaitEvent(&AppEven))
{
switch (AppEven.type) {
case SDL_KEYDOWN:
bRun = false;
break;
case SDL_QUIT:
bRun = false;
break;
default:
break;
}
}
}
cleanup(background, image, renderer, window);
SDL_Quit();
return 0;
}
上面的实现都很简单,关于这些理论知识我们都基本上没有写,因为如果写也是到网站到处去搜索,如果注解有什么不对的地方,请指出。文章中的代码可以到第二课给出的GIT地址下载 第二课:SDL Window的创建与显示,我们修改的代码教程完以后会上传到CSDN上。