最优化渲染及软拉伸

最优化渲染及软拉伸

目前为止,我们加载的图片只是屈指可数的,但是游戏呢?别忘了,想用这个来开发的程序游戏居多,就算不是游戏,显示成千上万的图片不过分吧,原始图片直接显示运行太慢了(相对来说),因此,我们需要优化。
别问,问就是恰好,SDL库可以有解决办法。

下面我们来学习把原始图片直接转化为优化格式,这就是最优化渲染,加快运行速度(放心,由于运行太快,同时本教程以一张图片为例,因此你观察不出来的。记住有这个事情就可,等哪天遇见了,得记住还有这个处理办法。)同时,我们的SDL2版本,是该长大了。于是我们有了可以拉伸图片的功能了,这就是软拉伸。

同样的,以中文代码形式讲解,英文代码为已经讲解过的部分,不加以阐述。
在文末划重点。

/*This source code copyrighted by Lazy Foo' Productions (2004-2020)
and may not be redistributed without written permission.*/
//为适应纯C语言,已经在源码基础上做出修改,与大佬开源有部分出入纯属正常
//Using SDL, standard IO, and strings
#include <SDL.h>
#include <stdio.h>
#include <string.h>
#include "struct_type.h"

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

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

//Loads individual image
SDL_Surface* loadSurface(char path[]);

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

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

//Current displayed image
SDL_Surface* gStretchedSurface = NULL;

bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Create window
		gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (gWindow == NULL)
		{
			printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Get window surface
			gScreenSurface = SDL_GetWindowSurface(gWindow);
		}
	}

	return success;
}

bool loadMedia()
{
	//Loading success flag
	bool success = true;

	//Load stretching surface
	gStretchedSurface = loadSurface("C:\\Users\\Lixin\\Desktop\\stretch.bmp");
	if (gStretchedSurface == NULL)
	{
		printf("Failed to load stretching image!\n");
		success = false;
	}

	return success;
}

void close()
{
	//Free loaded image
	SDL_FreeSurface(gStretchedSurface);
	gStretchedSurface = NULL;

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

	//Quit SDL subsystems
	SDL_Quit();
}

SDL_Surface* loadSurface(char path[])
{
	//The final optimized image
	SDL_Surface* optimizedSurface = NULL;

	//Load image at specified path
	SDL_Surface* loadedSurface = SDL_LoadBMP(path);
	if (loadedSurface == NULL)
	{
		printf("Unable to load image %s! SDL Error: %s\n", path, SDL_GetError());
	}
	else
	{
		//转变图片格式,实现加速
		optimizedSurface = SDL_ConvertSurface(loadedSurface, gScreenSurface->format, 0);
		if (optimizedSurface == NULL)
		{
			printf("Unable to optimize image %s! SDL Error: %s\n", path, SDL_GetError());
		}

		//释放老格式图片占用空间,避免内存泄漏
		SDL_FreeSurface(loadedSurface);
	}

	return optimizedSurface;
}

int main(int argc, char* args[])
{
	//Start up SDL and create window
	if (!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Load media
		if (!loadMedia())
		{
			printf("Failed to load media!\n");
		}
		else
		{
			//Main loop flag
			bool quit = false;

			//Event handler
			SDL_Event e;

			//While application is running
			while (!quit)
			{
				//Handle events on queue
				while (SDL_PollEvent(&e) != 0)
				{
					//User requests quit
					if (e.type == SDL_QUIT)
					{
						quit = true;
					}
				}

				//图片软拉伸
				SDL_Rect stretchRect;
				stretchRect.x = 0;
				stretchRect.y = 0;
				stretchRect.w = SCREEN_WIDTH;
				stretchRect.h = SCREEN_HEIGHT;
				SDL_BlitScaled(gStretchedSurface, NULL, gScreenSurface, &stretchRect);

				//Update the surface
				SDL_UpdateWindowSurface(gWindow);
			}
		}
	}

	//Free resources and close SDL
	close();

	return 0;
}
  1. 最优化渲染:查看加载位图时,通常以24位格式加载,因为大多数位图都是24位。默认情况下,大多数(如果不是全部)现代显示器不是24位。如果我们将24位的图像分割到32位图像上,SDL会在每次图像渲染时对其进行转换。因此,当加载图像时,我们要做的是将其转换为与屏幕相同的格式,因此无需在blit上进行转换。这可以通过SDL_ConvertSurface轻松完成。我们所要做的就是传入我们要用屏幕格式转换的表面。请务必注意,SDL_ConvertSurface以新格式返回原始副本。此调用后,原始加载的图像仍在内存中。这意味着我们必须释放原始加载的表面,否则我们将在内存中拥有同一图像的两个副本。加载并转换图像后,我们返回最终的优化图像。
  2. 图片软拉伸:SDL2新增了一项专用功能,可将图像缩小到不同的大小:SDL_BlitScaled。与之前的blitting 图像一样,SDL_BlitScaled将一个源表面连接到目标表面上。它还会引入目标SDL_Rect,该目标定义了您正在展示的图像的位置和大小。因此,如果我们要展示比屏幕小的图像并使其成为屏幕的大小,则可以将目标宽度(高度设置)为屏幕的宽度(高度)。

疫情退散!!!憋在宿舍写教程,呜呜呜~~~

posted @ 2022-01-07 11:12  LiXintao  阅读(150)  评论(0)    收藏  举报