要想了解 SDL 的事件处理,我们必须要知道的一个原理是,SDL将所有事件都存放在一个队列中。所有对事件的操作,其实就是对队列的操作。了解了这个原理后,我们再来说SDL提供的 API 就很容易理解了。
SDL只提供了这样几个简单的API,下面们来介绍几个常见的事件:
关于事件更加详的信息可以到 SDL Wiki 上进行查询。现在我们来看一个使用的例子吧。
在我们之前文章的例子中,大家已经发现一个问题,那就是窗口只显示了 3 秒钟,之后就自动消失了。
有的同学可以会通过修改代码最后面的 SDL_Delay 函数,增加它的等待时间让窗口多活一段时间。
但这样的体验实在是太糟糕了。有没有一种好的办法可以解决这个问题呢?能不能窗口一直显示,直到检测到用户按了ctrl+c
或 使用鼠标点击关闭按钮后才关闭呢?
当然是可以的。我们只需要在之前的程序的末尾增加下面这段代码即可。它会一直检测用户是否按下了退出按钮。如果检测到了,则直接退出,否则保持显示状态。
while(!quit){
SDL_Event event;
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
quit = 1;
break;
default:
SDL_Log(".");
}
}
}
增加了上面的代码,我们的实验程序似乎也显的很正规了。但有一个问题不知你发现没有 ?当我们打开任务管理器时,发现我们的程序居然占了 100% 的 CPU。My GOD!这个的结果是决对不能接受的。
是什么原因造成的呢?我们来仔细看一下我们增加的代码吧。它由两层 while 循环组成,最里面的while循环的意思是,当队列中一直能取出事件,那就让他一直做下去,直到事件队列为空。外面的while循环的意思是,当队列为空的时候,重新执行内部的while循环。
也就是说,这段代码一直在工作,从不休息。所以导致cpu占到了 100%。即然找到了问题的原因,我们就好处理了,只要在外层循环的最后 delay一下,让CPU休息一下就好了。
当然,SDL还为我们提供了 SDL_WaitEvent方法,使用这个API,你的CPU就不会跑到 100%了,因为当它发现队列为空时,它会阻塞在那里,并将CPU释放掉。
即然有 SDL_WaitEvent了,为什么还要有SDL_PollEvent呢?这主要是由于使用的场景不同。对于游戏来说,它要求事件的实时处理; 而对于一些其它实时性不高的case来说,则可以使用 SDL_WaitEvent了。
到此,本文的内容就介绍完了。在本文中主要介绍了SDL是如何处理事件的,SDL为我们提供了非常简单的API,这大大减少了我们的开发成本。
另外,我在文章的最后,介绍了SDL_PollEvent 与 SDL_WaitEvent两个 API的区别。这也是使用 SDL 事件处理中最容易引起困惑的地方。
希望本文能对您有所帮助,谢谢!