我想使用SDL用户事件来跟踪我的应用程序中的自定义事件。我的问题是SDL_UserEvent结构只提供一个int和两个void指针。
typedef struct{ Uint8 type; int code; void *data1; void *data2; } SDL_UserEvent;
我希望有一个具有以下结构的事件:
typedef struct{ Uint8 type; /* Set to SDL_USEREVENT + MAP */ int code; /* Set to MAP_COLLISION */ Uint8 tile_x; Uint8 tile_y; Uint8 tile_type; } UserEvent_MapCollision;
然后,每当我想处理MAP事件时,我就可以重新解释构造结构,如果不这样做,就可以抛弃消息而无需额外的处理。我的事件处理程序将使用这种技术进行简化(不需要malloc并释放此结构并将其附加到事件中)。
只要我检查(在构建时?)sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event)
,并且SDL事件队列没有以任何方式修改推送事件,这会有效吗?
答案 0 :(得分:2)
是的,它会起作用,请记住SDL_Event
结构本身是一个很大的union
。你是对的,如果你不确定你的结构是否适合SDL_Event
,你可以添加这个编译时断言:sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event)
。
/* Push event */
SDL_Event e;
UserEvent_MapCollision* p = static_cast<UserEvent_MapCollision*>(&e);;
e.type = SDL_USEREVENT + MAP;
e.code = MAP_COLLISION;
p.tile_x = 10;
p.tile_y = 20;
p.tile_type = 7;
/* Receive event */
SDL_Event e;
while (SDL_PollEvents(&e)) {
if (e.type == SDL_USEREVENT + MAP) {
if (e.user.code == MAP_COLLISION) {
UserEvent_MapCollision *p = static_cast<UserEvent_MapCollision>(&e)
HandleMapCollision(p);
}
}
}
要在编译时检查断言,您可以使用SDL宏SDL_COMPILE_TIME_ASSERT
,它在SDL_stdinc.h
中定义:
SDL_COMPILE_TIME_ASSERT(UserEvent_MapCollision, sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event));
作为旁注,这两个void*
指针旨在引用另一个结构。
typedef struct {
Uint8 tile_x;
Uint8 tile_y;
Uint8 tile_type;
} MyCustomEventStruct;
/* Create event */
SDL_UserEvent e;
MyCustomEventStruct *p;
p = new MyCustomEventStruct;
p->tile_x = 10;
p->tile_y = 20;
p->tile_type = 7;
e.type = SDL_USEREVENT + MAP;
e.code = MAP_COLLISION;
e.data1 = p;
e.data2 = 0;
SDL_PushEvent(&e);
/* Receive Event */
while (SDL_PollEvents(&e)) {
if (e.type == SDL_USEREVENT + MAP) {
if (e.user.code == MAP_COLLISION) {
MyCustomEventStruct* p = static_cast<MyCustomEventStruct*>(e.user.data1);
HandleMapCollision(p);
delete p;
}
}
}
答案 1 :(得分:1)
虽然这可行,但我认为你最好在函数或宏中做这样的事情:
Uint8 tile_x = static_cast<Uint8>(reinterpret_cast<uintptr_t>(sdl_event->data1) & 0xFF);
Uint8 tile_y = static_cast<Uint8>((reinterpret_cast<uintptr_t>(sdl_event->data1) >> 8) & 0xFF);
Uint8 tile_type = static_cast<Uint8>((reinterpret_cast<uintptr_t>(sdl_event->data1) >> 16) & 0xFF);
和此:
sdl_event->data1 = reinterpret_cast<void *>(
static_cast<uintptr_t>(tile_x) |
static_cast<uintptr_t>(tile_y) << 8 |
static_cast<uintptr_t>(tile_type) << 16 );