【SDL游戏编程入门第三卷】加载并缩放BMP图片

请添加图片描述

一、前言

本节介绍如何加载 BMP 图片,并且实现缩放效果

然后代码在上一小节的基础上稍微封装了一下,但是考虑到并不是真正的项目,所以并不会弄的太复杂,我们还是以解释每个功能以及效果的实现为主

二、加载 BMP 图片

使用函数:SDL_Surface* SDL_LoadBMP(const char* file)

正如函数名,这只能用来加载 BMP 格式的图片,如你所见,在用于画面展示时,我们经常会看到 SDL_Surface

使用该函数加载资源后,要记得在不使用的时候清除资源内存

本节程序用到的资源(该图片是 BMP 格式的图片,由于该站点不能上传 BMP 格式的图片,所以改了后缀,下载该资源使用时应该是 jpg 格式,可以改后缀也可以不改,因为二进制数据还是 BMP 格式,不影响)

三、显示到画面中

int SDL_BlitSurface(SDL_Surface* src, const SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect)

简单来说就是把一个表面通过位块传输复制到另一个表面中,不过这个函数会对图像进行原始的块传输

不能缩放,这里我们使用的是另一个函数,它可以缩放 BMP 图片,SDL_BlitScaled

注意:每次绘制过后,记得更新窗口表面,这次我们把这些操作放在窗口循环中

四、示例程序

/* 此源代码版权归 AnnihilateSword (2022-*)所有,未经书面许可不得转载。*/

// 使用 SDL 和 iostream
#include <SDL.h>
#include <iostream>

// 链接库
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")

// 屏幕尺寸常量
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

bool Init();								// 启动 SDL 并创建窗口
bool LoadMedia();							// 加载媒体
SDL_Surface* LoadSurface(const char* path); // 加载单个图像
void Close();								// 清理资源,关闭窗口以及SDL

SDL_Window* gWindow = nullptr;				// 主窗口
SDL_Surface* gWindowSurface = nullptr;		// 主窗口关联的表面

SDL_Surface* gTexture = nullptr;			// 需要加载的纹理(表面)

// 控制纹理坐标
int gTexturePosX = 100;
int gTexturePosY = 100;
int gTextureMovementSpeed = 20;

int main(int argc, char* argv[])			// 必须要填写此参数,不然会出现链接错误
{
	// 初始化 SDL
	if (Init())
	{
		// 窗口循环
		SDL_Event e;
		bool quit = false;
		while (quit == false)
		{
			// 处理事件
			while (SDL_PollEvent(&e))
			{
				if (e.type == SDL_QUIT)
					quit = true;
				else if (e.type == SDL_KEYDOWN)  // 处理按键按下事件
				{
					switch (e.key.keysym.sym)
					{
					case SDLK_w: gTexturePosY -= gTextureMovementSpeed; break;
					case SDLK_s: gTexturePosY += gTextureMovementSpeed; break;
					case SDLK_a: gTexturePosX -= gTextureMovementSpeed; break;
					case SDLK_d: gTexturePosX += gTextureMovementSpeed; break;
					}
				}
			}

			// --- rendering -----------------------------------------------------------------------
			// 将表面填充为蓝色
			SDL_FillRect(gWindowSurface, nullptr, SDL_MapRGB(gWindowSurface->format, 51, 76, 204));
			// 应用纹理
			SDL_Rect dstRect{ gTexturePosX, gTexturePosY, 341, 256 };
			// SDL_BlitSurface(gTexture, nullptr, gWindowSurface, &dstRect);  // 不缩放
			SDL_BlitScaled(gTexture, nullptr, gWindowSurface, &dstRect);

			// 更新表面
			SDL_UpdateWindowSurface(gWindow);
		}
	}
	// 清理资源
	Close();
	return 0;
}

/**
 * @brief 启动 SDL 并创建窗口
 */
bool Init()
{
	// 初始化 SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		std::cout << "[Error]: SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
		return false;
	}
	else
	{
		// 加载媒体资源
		if (!LoadMedia())
		{
			std::cout << "[Error]: Failed to load Media!" << std::endl;
		}
		else
		{
			// 创建窗口
			gWindow = SDL_CreateWindow("HelloSDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
			if (!gWindow)
			{
				std::cout << "[Error]: Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
			}
			else
			{
				// 获取窗口关联的表面
				gWindowSurface = SDL_GetWindowSurface(gWindow);
				if (!gWindowSurface)
					return false;
			}
		}
	}
	return true;
}

/**
 * @brief 加载媒体
 */
bool LoadMedia()
{
	gTexture = LoadSurface(R"(res\textures\Naruto.bmp)");
	if (!gTexture)
	{
		std::cout << "[Error]: Failed to load texture!" << std::endl;
		return false;
	}
	return true;
}

/**
 * @brief 加载单个图像
 * @param path:资源路径
 */
SDL_Surface* LoadSurface(const char* path)
{
	SDL_Surface* loadedSurface = SDL_LoadBMP(path);
	if (!loadedSurface)
		std::cout << "[Error]: Unable to load image " << path << " SDL Error: " << SDL_GetError() << std::endl;
	return loadedSurface;
}

/**
 * @brief 清理资源,关闭窗口以及SDL
 */
void Close()
{
	if (gTexture)
	{
		// 清理表面
		SDL_FreeSurface(gTexture);
		gTexture = nullptr;
	}

	// 销毁窗口
	SDL_DestroyWindow(gWindow);
	// 退出 SDL
	SDL_Quit();
}

1. 运行结果



本节内容就到这里了,下卷会继续分享 SDL 的基本使用

The End.

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值