在前面学习SDL的例子运行时,我们发现我们的窗口只停留了几秒,但是如果设置更长时间显然也有其他的弊端。

那么有没有一种好的办法可以解决这个问题呢?例如:能不能让窗口一直显示,直到检测到用户用鼠标点击关闭按钮后才关闭呢?

答:显然可以! 下面就来介绍一下SDL的事件处理机制。

1. SDL 事件处理机制原理

SDL事件就是键盘事件,鼠标事件,窗口事件等。SDL将所有事件都存放在一个队列中。所有对事件的操作,其实就是对队列的操作。

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

2. SDL 操作事件队列的API

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

3. SDL 处理事件的API

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

实战

在上面我们也说过了,如果不做SDL窗口的关闭事件的处理,我们是不能够通过点击关闭按钮,关闭SDL显示的窗口的。这样对用户是非常不友好的。

下面我们对SDL的Hello World代码做一下优化,其实就是在程序的末尾增加SDL_Event的事件处理,本例做的事情是检测用户是否按下了退出按钮。如果检测到了,则直接退出,否则保持显示状态。

代码实例:

// SDL.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include "pch.h"
#include <iostream>extern "C" {#include "SDL.h"
}int main(int argc, char* argv[])
{if (SDL_Init(SDL_INIT_VIDEO)) {std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;return 1;}SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);if (win == nullptr) {std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;return 1;}SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);if (ren == nullptr) {SDL_DestroyWindow(win);std::cout << "SDL_CreateRender Error: " << SDL_GetError() << std::endl;SDL_Quit();return 1;}std::string imagePath = "1.bmp";SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());if (bmp == nullptr) {SDL_DestroyRenderer(ren);SDL_DestroyWindow(win);std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;SDL_Quit();return 1;}SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);SDL_FreeSurface(bmp);if (tex == nullptr) {SDL_DestroyRenderer(ren);SDL_DestroyWindow(win);std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;SDL_Quit();return 1;}for (int i = 0; i < 3; ++i) {SDL_RenderClear(ren);SDL_RenderCopy(ren, tex, NULL, NULL);SDL_RenderPresent(ren);SDL_Delay(1000);}int quit = 1;do {SDL_Event event;SDL_WaitEvent(&event);switch (event.type) {case SDL_QUIT:SDL_Log("Event type is %d", event.type);quit = 0;default:SDL_Log("Event type is %d", event.type);break;}} while (quit);SDL_DestroyTexture(tex);SDL_DestroyRenderer(ren);SDL_DestroyWindow(win);SDL_Quit();// Returnreturn 0;
}

运行效果:
我们能看到同HelloWorld一样的界面输出,此时如果我们对SDL窗口不做任何处理的话,界面是不会消失的,当我们点击窗口的关闭按钮后,界面关闭了。

4. SDL_PollEvent 与 SDL_WaitEvent

细心的人会发现,使用 SDL_PollEvent 和使用 SDL_WaitEvent 两个方法都能处理SDL的事件队列。如果我们简单的将程序中的SDL_WaitEvent 替换为SDL_PollEvent ,运行时发现也没什么问题。但是当我们打开任务管理器时,发现我们的程序居然跑满了CPU。是什么原因造成的呢?我们来仔细看一下我们增加的代码吧。它由两层 while 循环组成,最里面的while循环的意思是,当队列中一直能取出事件,那就让他一直做下去,直到事件队列为空。外面的while循环的意思是,当队列为空的时候,重新执行内部的while循环。也就是说代码一直在工作,从不休息。所以导致CPU很快就跑满了。 而使用SDL_WaitEvent方法,CPU就不会出现这个问题,因为当它发现队列为空时,它会阻塞在那里,并将CPU占用释放掉。

SDL_WaitEvent和SDL_PollEvent这两个方法使用的场景不同:

  • 对于游戏来说,它要求事件的实时处理,我们最好使用SDL_PollEvent方法
  • 对于一些其它实时性不高的case来说,则可以使用 SDL_WaitEvent了

SDL 开发实战(四): SDL 事件处理相关推荐

  1. SDL 开发实战(五): SDL 纹理渲染

    本文我们讲一下如何使用SDL_Texture将视频纹理渲染出来. 1. SDL 视频渲染相关对象 SDL 视频渲染主要涉及到四个对象:SDL_Window.SDL_Render.SDL_Texture ...

  2. SDL 开发实战(二):SDL 2.0 核心 API 解析

    基本的SDL的使用思路,基本分为三部分:初始化 -> 循环渲染 -> 销毁释放资源. SDL 初始化相关方法 : SDL_Init(): 初始化SDL SDL_CreateWindow() ...

  3. SDL 开发实战(三):使用 SDL 绘制基本图形

    本文我们来讲一下,如何使用SDL的API绘制基本的图形. SDL中绘制基本图形的 API并不多,主要是 点.线.矩形.填充矩形.其它图形都可以通过 点.线.矩形组合出来. 1. 设置画笔的颜色 设置画 ...

  4. SDL 开发实战(一):SDL介绍

    一.什么是SDL? SDL是 "Simple DirectMedia Layer"的缩写,SDL是一个开源的跨平台的多媒体库,封装了复杂的音视频底层操作,简化了音视频处理的难度. ...

  5. CrazyWing:Python自动化运维开发实战 四、Python变量

    导语: 1.什么是变量 2.变量名称的命名 3.变量赋值 4.变量存储数据的方式 5.引用计数 什么是变量: python学习过程中会用到许多数据,那为了方便操作,需要把这些数据分别用一个简单的名字代 ...

  6. SDL开发(一):SDL简介及2.0核心API解析

    文章目录 零. 参考文献 一. 什么是SDL? 1. SDL 库分类 2. SDL 子系统分类 二. SDL2.0核心API解析 1. 初始化函数 SDL_Init() 2. 创建窗口 SDL_Cre ...

  7. 小程序云开发实战步骤教程

    ####前言: 在学习云开发的时候将自己的学习过程记录下来了,放在了网上,收获了一波好评,今天下午在办公室没有事情,也发现之前有人在博客里面评论,你这个教程还有一半哩,可能是csdn的自动搬运功能出来 ...

  8. 【C语言探索之旅】 第三部分第一课:SDL开发游戏之安装SDL

     内容简介 1.课程大纲 2.第三部分第一课: SDL开发游戏之安装SDL 3.第三部分第二课预告:SDL开发游戏之创建窗口和画布 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并 ...

  9. 【C语言探索之旅】第三部分第三课:SDL开发游戏之显示图像

    内容简介 1.第三部分第三课: SDL开发游戏之显示图像 2.第三部分第四课预告: SDL开发游戏之事件处理 第三部分第三课:SDL开发游戏之显示图像 上一课中,我们学习了如何加载SDL库(SDL_I ...

最新文章

  1. 【原创】Linux环境下的图形系统和AMD R600显卡编程(11)——R600指令集
  2. centos下添加的端口不能访问(防火墙关闭)
  3. SAP的软件是如何深刻影响着世界的?
  4. 6个座位办公室最佳位置_四人办公室座次的首选最佳座位在哪儿
  5. 2018.09.17-2018.09.23
  6. 马化腾又要发红包!648亿港元,最多腾讯2%股份,我酸了...
  7. 笔记——专访李运华:程序员如何在技术上提升自己
  8. oracle学习笔记-转
  9. java实现排兵布阵(回溯法)
  10. 【文本标注】文本标注工具brat的使用
  11. HTML/CSS 圆形头像
  12. android7.0版本适配(一):应用间文件文件共享——FileProvider
  13. esp32 鸿蒙,ESP8266最佳开发板--ESP-LAUNCHER开发板评测
  14. 什么是python大数据研发,它有什么特点吗
  15. python提前查成绩_利用Python来查询自己的成绩!想改成绩吗?我教你啊!
  16. 算法学习(动态规划)- 数塔问题
  17. 725 数模 空气污染问题研究 (15 五一 B)
  18. ArcGIS生成矢量的分层设色地形图
  19. 使用Maven命令行快速创建项目骨架(archetype)
  20. iOS中GIF图片的加载

热门文章

  1. 【论文粗读】(NeurIPS 2020) SwAV:对比聚类结果的无监督视觉特征学习
  2. Windows系统USB转串口固定COM口编号
  3. redis中key和value的存储大小限制
  4. java web 服务器推送技术--comet4j
  5. B端城配物流平台如何提高资金结算与分账效率?
  6. 怎么看曲线有没有斜渐近线_怎样判断一个曲线有无斜渐近线?
  7. 青岛大学附属医院辛海燕:打造空间分离、服务一体的多院区信息化建设
  8. 本地缓存需要高时效性怎么办_面试了字节、阿里等大厂,今年面试到底问什么?(Java岗)...
  9. 基于博弈理论的入侵检测与响应模型综述
  10. 四维世界概念(机器记忆)