SDL系列(二)—— 渲染窗口与BMP图片

本篇介绍如何使用 SDL2 ( Simple DirectMedia 2 )库。
它是一个(相对)易于使用的库,可以在不依赖于特定于操作的功能的情况下添加多媒体功能。
步骤:

  1. 初始化 sdl
    2. 窗口 SDL_Window,
    3. 表面 SDL_Surface,
    4. 绘制 SDL_XXX
  2. 退出(清理)
    初始化 SDL
    在做任何其他事情之前,您必须将 SDL 整体初始化。正如您所料, SDL_Init () 就是这样做
    的。如果要初始化 SDL 的所有部分,请传递 SDL_INIT_EVERYTHING 。
    SDL 还允许您单独初始化库的特定子集(或子系统)。要指定,请指定 SDL_Init ()的标志,
    或使用 SDL_InitSubSystem ()。如果您计划单独初始化子系统,只需将 0 传递给 SDL_Init ()。
    SDL_Init( SDL_INIT_EVERYTHING )
    创建一个窗口
    您必须创建程序将用于多媒体输入和输出的窗口。从头开始创建 Windows 应用程序时,
    必须定义" WinMain ",调用操作系统来获取句柄,创建窗口等等 .SDL 提供了一个更简单,
    与平台无关的窗口 API 。
    为了管理窗口, SDL 方便地提供结构 SDL_WindowSDL_CreateWindow () 等功能。
    略微切线:您可能会注意到 SDL_Window 没有文档链接。这是因为结构不透明 ; 你的程序无
    法看到" SDL_Window "中实际包含的内容。您只需管理指向 SDL_Window 的指针即可。
    SDL_CreateWindow ()执行您期望的操作:它接受指定窗口的名称,大小,位置和选项的
    参数,并返回指向新 SDL_Window 结构的指针。有关详细信息,请参阅 SDL 文档。
    SDL_Window *window ;
    window = SDL_CreateWindow( " 窗口名称 ", 100, 100, 1280, 720, SDL_WINDOW_SHOWN );
    大多数 SDL 函数将在失败时返回特定值。对于返回指针的函数,此值为 NULL 。因此,您可
    以轻松检查操作是否成功。
    发生任何错误后,函数 SDL_GetError ()允许您检索描述错误的字符串。
    if ( !window ) {
    cout << "Error creating window: " << SDL_GetError() << endl;
    return 1;
    }
    表面
    创建窗口后,您需要一种绘制方法。 SDL 将您可以绘制的任何区域(包括加载的图像)
    抽象为"表面"。(这是为了软件渲染 - 在未来,我们将进入 GPU 渲染 ,它不使用表面。)
    结构 SDL_Surface 和诸如 SDL_LoadBMP ()和 SDL_GetWindowSurface ()之类的函数提
    软件渲染 (也称为 blitting ) API 。
    正如您所期望的那样,使用 SDL_GetWindowSurface () 来获取窗口的表面。绘制到此表面
    后,可以通过调用 SDL_UpdateWindowSurface () 在窗口中看到结果。
    SDL_Surface* winSurface = SDL_GetWindowSurface( window );
    // 做绘画
    /// .....
    SDL_UpdateWindowSurface( win );
    绘制一个矩形
    要测试窗口表面是否正常工作,可以用颜色填充它。一个非常简单的方法是使用
    SDL_FillRect () 。要填充整个窗口,只需传递 NULL 而不是 SDL_Rect 指针。此外, SDL_FillRect
    ()采用表示颜色的特定格式编号。要获得此格式的颜色,可以使用曲面格式和所需的 RGB
    值调用 SDL_MapRGB 。
    SDL_FillRect( winSurface, NULL, SDL_MapRGB( winSurface->format, 255, 90, 120 ));
    退出
    一旦程序完成其操作,它必须销毁窗口并释放相关资源。正如您所料, SDL_DestroyWindow
    ()就是这么做的。该功能将关闭窗口,释放相关内存(包括窗口表面)。
    SDL_DestroyWindow( window );
    win = NULL;
    winSurface = NULL;
    最后,要关闭 SDL 作为一个整体,请调用 SDL_Quit ()。这是非常明确的。
    SDL_Quit();
    // 创建一个窗口
cpp 复制代码
int main_CreateWindow() {
	// Pointers to our window and surface
	/// 1.原理流程架构
	/// 2.数据结构+API
	SDL_Surface* winSurface = NULL;
	SDL_Window* window = NULL;

	// Initialize SDL. SDL_Init will return -1 if it fails.
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
		cout << "Error initializing SDL: " << SDL_GetError() << endl;
		return 1;
	}

	// Create our window
	window = SDL_CreateWindow("Example-Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 360, SDL_WINDOW_SHOWN);

	// Make sure creating the window succeeded
	if (!window) {
		cout << "Error creating window: " << SDL_GetError() << endl;
		return 1;
	}

	// Get the surface from the window
	winSurface = SDL_GetWindowSurface(window);

	// Make sure getting the surface succeeded
	if (!winSurface) {
		cout << "Error getting surface: " << SDL_GetError() << endl;
		return 1;
	}

	// Fill the window with a white rectangle
	SDL_FillRect(winSurface, NULL, SDL_MapRGB(winSurface->format, 255, 0, 0));

	// Update the window display
	SDL_UpdateWindowSurface(window);

	//Delay 3s
	SDL_Delay(3000);

	// Destroy the window. This will also destroy the surface
	SDL_DestroyWindow(window);

	// Quit SDL
	SDL_Quit();

	// End the program
	return 0;
}

// 显示BMP图片

cpp 复制代码
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main_ShowBMPImage()
{
	//The window we'll be rendering to
	SDL_Window* gWindow = NULL;

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

	//The image we will load and show on the screen
	SDL_Surface* gHelloWorld = NULL;

	//首先初始化   初始化SD视频子系统
	if (SDL_Init(SDL_INIT_VIDEO)<0)
	{
		printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
		return false;
	}
	//创建窗口
	gWindow = SDL_CreateWindow("SHOW BMP",//窗口标题
		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());
		return false;
	}
	//Use this function to get the SDL surface associated with the window.
	//获取窗口对应的surface
	gScreenSurface = SDL_GetWindowSurface(gWindow);

	//加载图片
	gHelloWorld = SDL_LoadBMP("./images/Hello_World.bmp");//加载图片
	if (gHelloWorld == NULL)
	{
		printf("Unable to load image %s! SDL Error: %s\n", "Hello_World.bmp", SDL_GetError());
		return false;
	}
	//Use this function to perform a fast surface copy to a destination surface.
	//surface的快速复制
	//下面函数的参数分别为: SDL_Surface* src ,const SDL_Rect* srcrect , SDL_Surface* dst ,  SDL_Rect* dstrect
	SDL_BlitSurface(gHelloWorld, NULL, gScreenSurface, NULL);
	SDL_UpdateWindowSurface(gWindow);//更新显示copy the window surface to the screen
	SDL_Delay(2000);//延时2000毫秒,2s后自动关闭

					//释放内存
	SDL_FreeSurface(gHelloWorld);//释放空间
	gHelloWorld = NULL;

	SDL_DestroyWindow(gWindow);//销毁窗口
	gWindow = NULL;

	SDL_Quit();//退出SDL

	return 0;
}

// 纹理与渲染

cpp 复制代码
int main_Render_Texture_demo()
{
	SDL_Window *window;
	SDL_Renderer *renderer;
	SDL_Texture *texture;
	SDL_Event event;
	SDL_Rect r;

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
		return 3;
	}

	window = SDL_CreateWindow("SDL_CreateTexture",
		SDL_WINDOWPOS_UNDEFINED,
		SDL_WINDOWPOS_UNDEFINED,
		1024, 768,
		SDL_WINDOW_RESIZABLE);

	r.w = 100;
	r.h = 100;

	/// render---->window
	renderer = SDL_CreateRenderer(window, -1, 0);

	/// texture-->render
	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1024, 768);

	// 跳来跳去的方块
	while (1) {
		SDL_PollEvent(&event);
		if (event.type == SDL_QUIT)
			break;
		r.x = rand() % 500;
		r.y = rand() % 500;

		SDL_SetRenderTarget(renderer, texture);
		SDL_SetRenderDrawColor(renderer, 0x88, 0x88, 0x88, 0x00);
		/// 将上一次render中的内容清空
		SDL_RenderClear(renderer);


		SDL_RenderDrawRect(renderer, &r);
		SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0x00);
		SDL_RenderFillRect(renderer, &r);
		SDL_SetRenderTarget(renderer, NULL);

		/// core: 复制内容
		SDL_RenderCopy(renderer, texture, NULL, NULL);
		SDL_RenderPresent(renderer);


		SDL_Delay(1000);
	}

	/// 清理、释放
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();
	return 0;
}
相关推荐
@小博的博客3 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生4 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步5 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
love_and_hope5 小时前
Pytorch学习--神经网络--搭建小实战(手撕CIFAR 10 model structure)和 Sequential 的使用
人工智能·pytorch·python·深度学习·学习
Chef_Chen5 小时前
从0开始学习机器学习--Day14--如何优化神经网络的代价函数
神经网络·学习·机器学习
芊寻(嵌入式)5 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
MediaTea6 小时前
Pr 视频过渡:沉浸式视频 - VR 色度泄漏
音视频·vr
LNTON羚通6 小时前
算法定制LiteAIServer摄像机实时接入分析平台烟火检测算法的主要功能
音视频·视频监控
hong1616886 小时前
跨模态对齐与跨领域学习
学习
阿伟来咯~7 小时前
记录学习react的一些内容
javascript·学习·react.js