2014-11-25 259 views
0

在我的SDL 1.2程序中,我有一個功能KeyPressed需要檢查一個鍵是否被按下。如果鼠標指針未在窗口前移動,則按下按鍵時,程序將按預期停止。另一方面,如果鼠標指針移動到窗口前,事件隊列似乎已經填滿,然後程序不響應按鍵。當沒有鍵盤事件時,有沒有辦法清空事件隊列?如何清空SDL事件隊列?

#include <SDL/SDL.h> 
#include <stdio.h> 

static void Init(int *error) 
{ 
    SDL_Surface *display; 

    *error = SDL_Init(SDL_INIT_VIDEO); 
    if (! *error) { 
     display = SDL_SetVideoMode(640, 480, 8, 0); 
     if (display != NULL) { 
      *error = 0; 
     } else { 
      fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); 
      *error = 1; 
     } 
    } else { 
     fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); 
     *error = 1; 
    } 
} 


static int KeyPressed(void) 
{ 
    SDL_Event event; 
    int count, result; 

    result = 0; 
    SDL_PumpEvents(); 
    count = SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN)); 
    switch (count) { 
     case -1: 
      fprintf(stderr, "SDL_PeepEvents: %s\n", SDL_GetError()); 
      break; 
     case 0: 
      break; 
     case 1: 
      result = 1; 
      break; 
    } 
    return result; 
} 


int main(void) 
{ 
    int error; 

    Init(&error); 
    if (! error) { 
     do { 
      /*nothing*/ 
     } while (! KeyPressed()); 
    } 
    return error; 
} 
+0

您必須從事件隊列中刪除事件,您是否嘗試過使用SDL_GETEVENT而不是SDL_PEEKEVENT? – nos 2014-11-25 14:35:09

+0

@nos好的,但我應該刪除多少事件?據我所知,沒有辦法獲得事件隊列的長度。 – 2014-11-25 15:20:43

+1

如果您首次執行SDL_PEEKEVENT,則會執行循環,如果返回非零值,則執行SDL_GETEVENT。如果它返回零,則清空事件隊列。雖然,目前還不清楚這個代碼是否只是真正的應用程序的一部分 - 控制流和檢查關鍵事件通常會非常不同 - 並且經常按照這裏所示進行處理http://stackoverflow.com/questions/3741055/inputs- in-sdl-on-key-pressed – nos 2014-11-25 15:29:29

回答

0

下面的解決方案,通過Zammalad的評論靈感似乎工作。當沒有找到按鍵事件時,我們從隊列中移除一個事件(通常是鼠標事件),爲新事件騰出空間。爲了使代碼更健壯,我還用事件替換了標量事件

#define LEN(a) ((int) (sizeof (a)/sizeof (a)[0])) 

static int KeyPressed(void) 
{ 
    SDL_Event events[1]; 
    int count, result; 

    result = 0; 
    SDL_PumpEvents(); 
    /*search the event queue for key down events*/ 
    count = SDL_PeepEvents(events, LEN(events), SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN)); 
    switch (count) { 
     case -1: 
      fprintf(stderr, "SDL_PeepEvents: %s\n", SDL_GetError()); 
      break; 
     case 0: 
      /*make room for new events by removing (non-key down) event from the queue*/ 
      count = SDL_PeepEvents(events, LEN(events), SDL_GETEVENT, -1); 
      if ((count > 0) && (events[0].type == SDL_QUIT)) { 
       exit(EXIT_SUCCESS); 
      } 
      break; 
     case 1: 
      result = 1; 
      break; 
    } 
    return result; 
} 
2

你應該使用輪詢,因爲他們的處理方式,將彈出隊列中的事件來檢查事件在while循環。使用多個if/then語句或swicth塊來處理事件。我推薦這種方法,你可以很容易錯過重要的事件,如SDL_QUIT使用SDL_PeepEvent

基本例如當:

SDL_Event e; 
while (SDL_PollEvent(&e)) 
{ 
    if (e.type == SDL_QUIT) 
    { 
     // do something here 
    } 
} 
+0

感謝您的輸入。然而,在我正在處理函數* KeyPressed *的實際代碼中,這是一個無法更改的API的一部分。否則,我會聽從你的建議。 – 2014-11-25 17:57:34

+2

在這種情況下,您應該檢查帶有事件掩碼的事件隊列,就像您在代碼中查看是否沒有按鍵事件一樣。如果沒有,請檢查是否沒有重要事件需要以同樣的方式處理SDL_QUIT。然後,您使用SDL_PeepEvent來刪除所有使用SDL_GETEVENT的事件。看到這裏 - https://wiki.libsdl.org/SDL_PeepEvents – Zammalad 2014-11-25 19:33:07

+0

您的評論中的方法似乎工作。 – 2014-11-27 09:09:36