「SDL第四篇」事件处理

作者: 音视频直播技术专家 | 来源:发表于2018-04-09 00:21 被阅读125次

    前言

    前面我为大家介绍了 SDL 的三个主题:

    今天我为大家介绍一下SDL的事件处理。这里所指的事件处理就是我们通常所说的,键盘事件,鼠标事件,窗口事件等。

    SDL对这些事件都做了封装,提供了统一的API,下面我们就来详细的看一下。

    SDL中的事件处理

    要想了解 SDL 的事件处理,我们必须要知道的一个原理是,SDL将所有事件都存放在一个队列中。所有对事件的操作,其实就是对队列的操作。了解了这个原理后,我们再来说SDL提供的 API 就很容易理解了。

    • SDL_PollEvent: 将队列头中的事件抛出来。
    • SDL_WaitEvent: 当队列中有事件时,抛出事件。否则处于阻塞状态,释放 CPU。
    • SDL_WaitEventTimeout: 与SDL_WaitEvent的区别时,当到达超时时间后,退出阻塞状态。
    • SDL_PeekEvent: 从队列中取出事件,但该事件不从队列中删除。
    • SDL_PushEvent: 向队列中插入事件。

    SDL只提供了这样几个简单的API,下面们来介绍几个常见的事件:

    • SDL_WindowEvent : Window窗口相关的事件。
    • SDL_KeyboardEvent : 键盘相关的事件。
    • SDL_MouseMotionEvent : 鼠标移动相关的事件。
    • SDL_QuitEvent : 退出事件。
    • SDL_UserEvent : 用户自定义事件。

    关于事件更加详的信息可以到 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(".");
            }
        }
    }
    

    SDL_PollEvent 与 SDL_WaitEvent

    增加了上面的代码,我们的实验程序似乎也显的很正规了。但有一个问题不知你发现没有
    ?当我们打开任务管理器时,发现我们的程序居然占了 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 事件处理中最容易引起困惑的地方。

    希望本文能对您有所帮助,谢谢!

    相关文章

      网友评论

      本文标题:「SDL第四篇」事件处理

      本文链接:https://www.haomeiwen.com/subject/scevhftx.html