第四课:多个Texture的绘制

 上一课我们讲解了关于如何用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上。

你可能感兴趣的:(SDL2教程)