0

我想使用 SDL 用户事件来跟踪我的应用程序中的自定义事件。我的问题是 SDL_UserEvent 结构只提供了一个 int 和两个 v​​oid 指针。

类型定义结构{
  uint8 类型;
  整数代码;
  无效*数据1;
  无效*数据2;
} SDL_用户事件;

我希望有一个具有以下结构的事件:

类型定义结构{
  uint8 类型;/* 设置为 SDL_USEREVENT + MAP */
  整数代码;/* 设置为 MAP_COLLISION */
  Uint8 tile_x;
  Uint8 tile_y;
  Uint8 瓦片类型;
} UserEvent_MapCollision;

然后,只要我想处理 MAP 事件,我就可以重新解释该结构,如果我不这样做,则无需额外处理即可丢弃该消息。使用这种技术可以简化我的事件处理程序(无需 malloc 和释放此结构并将其附加到事件)。

只要我检查(在构建时?)sizeof(UserEvent_MapCollision) <= sizeof(SDL_Event),并且 SDL 事件队列不会以任何方式修改推送的事件,这会起作用吗?

4

2 回答 2

3

是的,它会起作用,记住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;
        }
    }
}
于 2012-05-08T13:31:43.243 回答
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 );
于 2012-05-08T13:31:33.820 回答