事件循环
大多数多媒体程序依靠
事件系统
来处理输入。
SDL
为处理输入事件提供了灵活的
API
。
本质上,
SDL
将来自设备(如键盘,鼠标或控制器)的输入记录为
事件
,将它们存储在
“
事件队列
”中。
您可以将此结构视为等待线
-
事件在线的后面排队并从线的前面取出。
在您的程序中,您将始终拥有一个
事件(或“游戏”或“主”)循环
来处理这些事件
并根据输入运行您的程序。每次运行事件循环时,必须从事件队列中拉出每个事件(按顺序)
以处理输入。这是通过函数
SDL_PollEvent
()
完成的。此函数从队列中删除第一个事件,
将值复制到
SDL_Event
类型的参数中。如果事件队列为空,则该函数将返回
0
。
轮询事件后,您可以在逻辑链中使用它来推断输入内容和响应方式。
SDL_Event
SDL_Event 包含任何子事件之一。这可以通过使用联合来实现。
union
描述了结构中的
几个互斥数据成员。这意味着子事件类型都存储在同一个内存中,因此
SDL_Event
可以灵活
而不浪费空间。但是,这个系统使语法稍微笨拙
-
访问子事件数据,首先必须访问
SDL_Event
中的子事件。
退出
当用户希望关闭程序时, 您的事件循环将收到 SDL_QUIT
类型的事件。这包括按下窗口
上的“
x
”,按
ALT + F4
,或以其他方式请求程序结束。这不包括结束进程或将
CTRL + C
发送
到控制台
-
这些是不受控制的,立即中止。
因此,当您的程序收到 SDL_QUIT
事件时,它应该正常关闭(或提示用户提供更多信息)。
事件的类型可通过其“类型”成员访问。
键盘事件
键盘事件有两种形式 - SDL_KEYDOWN
和
SDL_KEYUP
。这两种类型都与
SDL_KeyboardEvent
相关联,后者包括键码和表示输入事件的标志。
是否按下/
释放
/
重复键可以通过
SDL_KeyboardEvent
的状态和重复成员来确定,而键码和修
饰键在
keysym
成员(
SDL_Keysym
)中指定。
键盘轮询
有一种方法可以在没有事件系统的情况下获得键盘输入。这是通过直接轮询键盘。建议
不要这样做,因为轮询键盘会为您提供当时的状态,而不是自上次轮询以来发生的每个事件
的日志。但是,轮询仍然偶尔会有用,因此
SDL
提供了函数
SDL_GetKeyboardState
()。此
函数返回包含键值的值数组。这个数组是持久的
-
它将在处理键盘事件时更新。
要访问密钥阵列中的数据,可以使用
SDL_Scancode
。
扫描码类似于
SDL_KeyboardEvent
的键值,而是作为键盘状态数组的索引。
鼠标事件
所有类型的事件都类似于键盘事件,
因为它们具有包含多个描述输入的数据成员的事件类型。
鼠标事件可以是
SDL_
MOUSEMOTION
,
SDL_
MOUSEBUTTONDOWN
,
SDL_
MOUSEBUTTONUP
和
SDL_
MOUSEWHEEL
类型。
这些类型与
SDL_
MouseButtonEvent
,
SDL_
MouseMotionEvent
和
SDL_
MouseWheelEvent
相关联。所有这些类型都包括鼠标事件的 x
和
y
坐标,以及额外的数据和修饰符。
// 完整示例代码:
#include "stdafx.h"
#include <SDL.h>
#undef main
int main__event2(int, char**)///__event2
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window* win = SDL_CreateWindow("yx3sxmeng", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
SDL_Surface* surface = SDL_LoadBMP("./Hello_world.bmp");
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
///1. window-->render(GPU, window), surface内存信息(bitmap), texture描述信息(render, bitmap|surface);
///2. SDL事件循环机制
bool quit = false;
SDL_Event ev;
SDL_Rect rect = { 0,0,800,600 };///目标位置大小(x,y, w,h);
int sx = 0, sy = 0;
while (!quit)
{
while (SDL_PollEvent(&ev))
{
switch (ev.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONDOWN:
sx = ev.button.x + rect.x;
sy = ev.button.y + rect.y;
break;
case SDL_MOUSEMOTION:
if (ev.motion.state & SDL_BUTTON_LMASK)
{
rect.x = ev.motion.x - sx;
rect.y = ev.motion.y - sy;
}
break;
case SDL_KEYDOWN:
if (ev.key.keysym.sym == SDLK_LEFT)
{
rect.x -= 10;
printf("SDLK_LEFT...");
}
else if (ev.key.keysym.sym == SDLK_RIGHT)
{
printf("SDLK_RIGHT...");
rect.x += 10;
}
else if (ev.key.keysym.sym == SDLK_UP)
{
printf("SDLK_UP...");
rect.w += 10;
rect.h += 10;
}
else if (ev.key.keysym.sym == SDLK_DOWN)
{
printf("SDLK_DOWN...");
rect.w -= 10;
rect.h -= 10;
}
printf("scancode=%d\n", ev.key.keysym.scancode);
break;
case SDL_MOUSEWHEEL:
if (ev.wheel.y > 0)
{
rect.h *= 1.1;
rect.w *= 1.1;
}
if (ev.wheel.y < 0)
{
rect.w /= 1.1;
rect.h /= 1.1;
}
break;
}
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_RenderPresent(renderer);
SDL_Delay(16);
}
//释放资源
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}