事件驱动

事件驱动

现在有了图像,那也得学习SDL处理事件的系统

在之前的代码框架里面实现以下代码

现在我们直接学习事件,在我看来,事件无非就是用户的一切输入,比如按键,鼠标点击,文本输入等等……,我想,我们首先应该学习的就是程序的关闭,这也属于一个事件。

下面继续C语言的模块化编程,因此,我们需要将关闭功能进行封装成模块,这需要我们对代码进行再次重构。

先看看完整代码,如果看不懂,先暂时略过,在下面我将详细的解释为啥需要这样书写。

/*This source code copyrighted by Lazy Foo' Productions (2004-2020)
and may not be redistributed without written permission.*/

//Using SDL and standard IO
#include <SDL.h>
#include <stdio.h>

//窗口长宽设置
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//初始化窗口
bool init();

//加载媒体信息
bool loadMedia();

//释放媒体资源,关闭窗口
void close();

//窗口指针
SDL_Window* gWindow = NULL;
	
//指向窗口表面缓存区
SDL_Surface* gScreenSurface = NULL;

//展示在屏幕上的
SDL_Surface* gXOut = NULL;

bool init()
{
	//完成初始化标志
	bool success = true;

	//SDL初始化
	if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
		printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
		success = false;
	}
	else
	{
		//创建窗口
		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
		{
			//获取窗口表层
			gScreenSurface = SDL_GetWindowSurface( gWindow );
		}
	}

	return success;
}

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

	//加载图片资源
	gXOut = SDL_LoadBMP( "03_event_driven_programming/x.bmp" );
	if( gXOut == NULL )
	{
		printf( "Unable to load image %s! SDL Error: %s\n", "03_event_driven_programming/x.bmp", SDL_GetError() );
		success = false;
	}

	return success;
}

void close()
{
	//释放资源
	SDL_FreeSurface( gXOut );
	gXOut = NULL;

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

	//退出SDL
	SDL_Quit();
}

int main( int argc, char* args[] )
{
	//初始化并建立一个窗口
	if( !init() )
	{
		printf( "Failed to initialize!\n" );
	}
	else
	{
		//加载图片信息
		if( !loadMedia() )
		{
			printf( "Failed to load media!\n" );
		}
		else
		{			
			//主循环标志
			bool quit = false;

			//事件处理
			SDL_Event e;

			//主程序运行
			while( !quit )
			{
				//处理事件队列
				while( SDL_PollEvent( &e ) != 0 )
				{
					//用户请求退出
					if( e.type == SDL_QUIT )
					{
						quit = true;
					}
				}

				//将图片资源装载进缓存区
				SDL_BlitSurface( gXOut, NULL, gScreenSurface, NULL );
			
				//切换渲染层,即上节课讲过的缓存区概念
				SDL_UpdateWindowSurface( gWindow );
			}
		}
	}

	//关闭
	close();

	return 0;
}
  1. 在本次课程中,最重要的是对于事件机制的学习,SDL事件机制是使用队列来存储,即先进先出原则。SDL_PollEvent( &e )函数每次会从事件队列里面弹出一个事件,因此我们循环检测e的事件是否为SDL_QUIT,如果是,就直接退出主循环。
  2. 对于大多数主程序,肯定不希望运行一次就选择直接退出。窗口程序也是一样,我们需要一直运行,时刻监视用户的行为。用户不想退出就持续运行,直到用户发出退出指令才选择退出。因此,我们会有一个主循环,这在以后的代码里面将很常见。
  3. 对于一些参数的定义,大佬写的代码显得非常精致。首先,在窗口大小上,直接采用常量进行处理,因为通常在建立了一个窗口之后,我们此时不希望更改窗口的大小。
  4. 在代码量很小的时候,大范围使用全局变量确实很舒服,但是一份代码有他自己的一个"命名空间"(我发明的一个词语),也就是说,全局变量会占用命名空间,当命名空间很大的时候,会引起变量重复定义或我们认为意义不同的两个变量使用同一个名字。这类错误是很难察觉的,遇见了就自求多福吧。
posted @ 2022-01-07 11:10  LiXintao  阅读(74)  评论(0)    收藏  举报