SDL简介

SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。

SDL1.2和SDL2的差别

SDK1.2和SDL2.1系列的API接口变动的不小,当然功能也大大增强,支持多线程窗口。

具体的change 请看

http://blog.csdn.net/yue7603835/article/details/42030667  我转载的 官方的 文章。

下面是 SDL2.0 例子代码的 事件CheckKeys代码的分析 +注释

SDK2.0例子代码分析-检测键盘按下状态

/* 监听键盘按下次数
你需要调用  SDL_PollEvent() or SDL_WaitEvent() to
   推动事件循环和 监视
   */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "SDL.h"

/*退出程序之前先清理 SDL subsystem */
static void
quit(int rc)
{  
	SDL_Quit();
	exit(rc);
}

//格式化 可变参数 到 buffer
static void
print_string(char **text, size_t *maxlen, const char *fmt, ...)
{
	int len;
	//定义可变参数列表 
	va_list ap;
	///初始化可变参数列表 
	va_start(ap, fmt);
	//格式化所有参数到text二维数组 并且返回字符长度
	len = SDL_vsnprintf(*text, *maxlen, fmt, ap);
	//如果返回>0 字符指针后移
	if (len > 0) {
		//
		*text += len;
		//如果len<最大尺寸那么 减少最大尺寸  否则置零
		if (((size_t)len) < *maxlen) {
			*maxlen -= (size_t)len;
		}
		else {
			*maxlen = 0;
		}
	}
	va_end(ap);
}

static void
print_modifiers(char **text, size_t *maxlen)
{
	int mod;
	print_string(text, maxlen, " modifiers:"); 
	//获取当前键盘状态判断 SHIFT等是否按下 
	mod = SDL_GetModState();
	if (!mod) {
		print_string(text, maxlen, " (none)");
		return;
	}
	if (mod & KMOD_LSHIFT)
		print_string(text, maxlen, " LSHIFT");
	if (mod & KMOD_RSHIFT)
		print_string(text, maxlen, " RSHIFT");
	if (mod & KMOD_LCTRL)
		print_string(text, maxlen, " LCTRL");
	if (mod & KMOD_RCTRL)
		print_string(text, maxlen, " RCTRL");
	if (mod & KMOD_LALT)
		print_string(text, maxlen, " LALT");
	if (mod & KMOD_RALT)
		print_string(text, maxlen, " RALT");
	if (mod & KMOD_LGUI)
		print_string(text, maxlen, " LGUI");
	if (mod & KMOD_RGUI)
		print_string(text, maxlen, " RGUI");
	if (mod & KMOD_NUM)
		print_string(text, maxlen, " NUM");
	if (mod & KMOD_CAPS)
		print_string(text, maxlen, " CAPS");
	if (mod & KMOD_MODE)
		print_string(text, maxlen, " MODE");
}

static void
//SDL_Keysym系统键 被SDL_EVENT所使用
PrintKey(SDL_Keysym * sym, SDL_bool pressed, SDL_bool repeat)
{   
	//存放消息
	char message[512]; 
	//指向message的指针
	char *spot;
	size_t left;

	spot = message;
	//left初始化=512
	left = sizeof(message);

	/*打印键盘码  状态  名字 */
	if (sym->sym) {
		print_string(&spot, &left,
			"Key %s:  scancode %d = %s, keycode 0x%08X = %s ",
			pressed ? "pressed " : "released",
           ///扫描码
			sym->scancode,
			//获取扫描码名字 
			SDL_GetScancodeName(sym->scancode), 
			 //获取key name
			sym->sym, SDL_GetKeyName(sym->sym));
	}
	else {
		print_string(&spot, &left,
			"Unknown Key (scancode %d = %s) %s ",
			sym->scancode,
			//获取键盘扫描码名字
			SDL_GetScancodeName(sym->scancode),
			pressed ? "pressed " : "released");
	}
	//打印当前键盘是否有系统键被按下
	print_modifiers(&spot, &left);
	if (repeat) {
		//如果重复按下 那么格式化字符串到 buffer  message
		print_string(&spot, &left, " (repeat)");
	}
	SDL_Log("%s\n", message);
}

//
static void
PrintText(char *text)
{
	char *spot, expanded[1024];

	expanded[0] = '\0';
	for (spot = text; *spot; ++spot)
	{ 
		//格式化
		size_t length = SDL_strlen(expanded);
		//将字符串格式化到buffer
		SDL_snprintf(expanded + length, sizeof(expanded) - length, "\\x%.2x", (unsigned char)*spot);
	}
	//打印日志 
	SDL_Log("Text (%s): \"%s%s\"\n", expanded, *text == '"' ? "\\" : "", text);
}

int
main(int argc, char *argv[])
{
	//创建SDLwindow
	SDL_Window *window;

	//sdl事件处理
	SDL_Event event;
	int done;

	/* 设置应用程序日志级别*/
	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

	/* 初始化SDL子系统*/
	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
		return (1);
	}

	/* 创建SDL 2d渲染窗口 */
	window = SDL_CreateWindow("CheckKeys Test",
		SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,

		640, 480, 0);
	//sdl 2d渲染窗口创建失败
	if (!window) {
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n",
			SDL_GetError());
		quit(2);
	}

	//如果是IPHONE下创建一个OpenGL渲染上下文并使其成为当前窗口
#if __IPHONEOS__
	SDL_GL_CreateContext(window);
#endif
	//开始接受Unicode文本输入事件  如果支持的话将会显示屏幕键盘
	SDL_StartTextInput();

	/* 监视键盘点击次数*/
	done = 0;
	//类似与 windows 消息循环 实际上底层在windows平台也是封装的 windows消息循环机制
	while (!done)
	{
		/* 事件监测循环检测 事件 */
		SDL_WaitEvent(&event);
		//event.type存储了当前的事件类型
		//如果无键盘鼠标 触摸点击 那么 默认是 0x200 
		switch (event.type)
		{
		case SDL_KEYDOWN:
		case SDL_KEYUP:
			//打印系统键信息
			PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE);
			break;
		case SDL_TEXTINPUT:
			//如果是文本输入 输出文本
			PrintText(event.text.text);
			break;
		case SDL_MOUSEBUTTONDOWN:
			/* 如果有任何鼠标点击消息 或者SDL_QUIT消息 那么将退出窗口 */
		case SDL_QUIT:
			done = 1;
			break;
		default:
			break;
		}
	}
	//清除已经初始化的子系统 你应该在程序退出的时候调用
	SDL_Quit();
	return (0);
}


Logo

更多推荐