0

SDL User Events を使用して、アプリケーションのカスタム イベントを追跡したいと考えています。私の問題は、SDL_UserEvent 構造体が 1 つの int ポインターと 2 つの void ポインターしか提供しないことです。

typedef構造体{
  Uint8 型;
  int コード;
  ボイド * データ 1;
  ボイド * データ 2;
} SDL_UserEvent;

次のような構造のイベントを開催したいと考えています。

typedef構造体{
  Uint8 型; /* SDL_USEREVENT + MAP に設定 */
  int コード; /* MAP_COLLISION に設定 */
  Uint8 tile_x;
  Uint8 tile_y;
  Uint8 tile_type;
} 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));

ちなみに、これら2つの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 に答える