在 'while' 中测试 'SDL_PollEvent' 的正确方法
The correct way to test 'SDL_PollEvent' in a 'while'
正如手册所说,函数 SDL_PollEvent
"Returns 1 if there is a pending event or 0 if there are none available." ,这就是我们使用测试 SDL_PollEvent(&e)!=0
的原因(其中 e
是 SDL_Event
)。
但是,使用这个测试怎么样:!SDL_PollEvent(&e)
?它应该可以工作,但显然它会引起一些问题。
这里有一个代码示例:
#include <SDL2/SDL.h>
#include <stdio.h>
int main(int argc, char* args[]){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Hello",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 100, 100, SDL_WINDOW_SHOWN);
SDL_Event e;
int quit=0;
while(!quit){
//Here the test
while (!SDL_PollEvent(&e)){
if (e.type==SDL_QUIT)
quit=1;
else if ( e.type == SDL_KEYDOWN )
printf( "Hello\n" );
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
这段代码应该做的是打开一个新的 window 并在每次按下某个键时在控制台中打印 "Hello" 。这段代码在测试 SDL_PollEvent(&e)!=0
时工作正常,但是当我使用测试 !SDL_PollEvent(&e)
时它没有读取 SDL_KEYDOWN
事件(但它确实在 while 中输入并处理 SDL_QUIT
事件没有任何问题)。
为什么会出现这种行为?
while (!SDL_PollEvent(&e))
需要:
while (SDL_PollEvent(&e))
如果应该和SDL_PollEvent(&e) != 0
一样
因为!SDL_PollEvent(&e)
等同于调用while(0)
(1 != 0)
为真,(!1)
为假。
无论如何,您可能应该使用 SDL_WaitEvent
。
附录
人们可能认为这样做更清楚,因为它可以确保对用户输入做出反应。然而,这目前是一个 OS 依赖并且可能是疯狂的 CPU 猪并且会最大化你的 CPU 这个线程(在 Windows 上)。所以你可能认为你可以在那里等待 1 秒,但是你的 window 将变得完全没有反应或充其量非常迟钝......
如果您可以忍受一点 CPU 无所事事的开销,那么您可以妥协使用 20-100 [ms] 延迟。
...
// Set the event handler...
...
bool isRunning = true;
while (isRunning) {
// Do the main thing here...
...
while(SDL_PollEvent(&windowEvent)) {
switch (windowEvent.type) {
case SDL_QUIT: isRunning = false;
case SDL_KEYDOWN: isRunning = false;
case SDL_MOUSEBUTTONDOWN: isRunning = false;
break;
}
SDL_Delay(100); // Wrong!
}
}
// End the program
很明显这也不是正确的方法。我们需要使用一些其他机制。查看 SDL 回购协议,我们发现了一个很长但非常相关的关于未解决问题的讨论:
解决问题
确保在 SDL_PollEvent()
.
之前将延迟放在外循环中
// main loop
...
while(SDL_PollEvent(&windowEvent)) {
switch (windowEvent.type) {
case SDL_QUIT: isRunning = false;
case SDL_KEYDOWN: isRunning = false;
case SDL_MOUSEBUTTONDOWN: isRunning = false;
break;
}
}
SDL_Delay(100); // Right!
}
正如手册所说,函数 SDL_PollEvent
"Returns 1 if there is a pending event or 0 if there are none available." ,这就是我们使用测试 SDL_PollEvent(&e)!=0
的原因(其中 e
是 SDL_Event
)。
但是,使用这个测试怎么样:!SDL_PollEvent(&e)
?它应该可以工作,但显然它会引起一些问题。
这里有一个代码示例:
#include <SDL2/SDL.h>
#include <stdio.h>
int main(int argc, char* args[]){
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("Hello",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 100, 100, SDL_WINDOW_SHOWN);
SDL_Event e;
int quit=0;
while(!quit){
//Here the test
while (!SDL_PollEvent(&e)){
if (e.type==SDL_QUIT)
quit=1;
else if ( e.type == SDL_KEYDOWN )
printf( "Hello\n" );
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
这段代码应该做的是打开一个新的 window 并在每次按下某个键时在控制台中打印 "Hello" 。这段代码在测试 SDL_PollEvent(&e)!=0
时工作正常,但是当我使用测试 !SDL_PollEvent(&e)
时它没有读取 SDL_KEYDOWN
事件(但它确实在 while 中输入并处理 SDL_QUIT
事件没有任何问题)。
为什么会出现这种行为?
while (!SDL_PollEvent(&e))
需要:
while (SDL_PollEvent(&e))
如果应该和SDL_PollEvent(&e) != 0
因为!SDL_PollEvent(&e)
等同于调用while(0)
(1 != 0)
为真,(!1)
为假。
无论如何,您可能应该使用 SDL_WaitEvent
。
附录
人们可能认为这样做更清楚,因为它可以确保对用户输入做出反应。然而,这目前是一个 OS 依赖并且可能是疯狂的 CPU 猪并且会最大化你的 CPU 这个线程(在 Windows 上)。所以你可能认为你可以在那里等待 1 秒,但是你的 window 将变得完全没有反应或充其量非常迟钝...... 如果您可以忍受一点 CPU 无所事事的开销,那么您可以妥协使用 20-100 [ms] 延迟。
...
// Set the event handler...
...
bool isRunning = true;
while (isRunning) {
// Do the main thing here...
...
while(SDL_PollEvent(&windowEvent)) {
switch (windowEvent.type) {
case SDL_QUIT: isRunning = false;
case SDL_KEYDOWN: isRunning = false;
case SDL_MOUSEBUTTONDOWN: isRunning = false;
break;
}
SDL_Delay(100); // Wrong!
}
}
// End the program
很明显这也不是正确的方法。我们需要使用一些其他机制。查看 SDL 回购协议,我们发现了一个很长但非常相关的关于未解决问题的讨论:
解决问题
确保在 SDL_PollEvent()
.
// main loop
...
while(SDL_PollEvent(&windowEvent)) {
switch (windowEvent.type) {
case SDL_QUIT: isRunning = false;
case SDL_KEYDOWN: isRunning = false;
case SDL_MOUSEBUTTONDOWN: isRunning = false;
break;
}
}
SDL_Delay(100); // Right!
}