SDL 2.0课程周期:第4课-处理事件

SDL2

来自翻译者:

这是Twinklebear教程的一系列翻译的延续,该教程最初在此处提供 该翻译是部分免费的,并且可能包含翻译人员的少量修改或补充。 前两节课的翻译由InvalidPointer编写。 原始文章中的图片已本地化,并最大限度地保留了作者的风格。

课程清单:



事件处理


在本课程中,我们将学习获取用户输入的基础知识,并且为了简单起见,我们将把任何用户操作都视为逃避终止程序的尝试。 SDL使用事件队列中的SDL_Event结构和事件提取功能(例如SDL_PollEvent)来检索有关事件的信息。 作为本课程一部分编写的代码基于上一课程的结果。

但是首先,让我们在屏幕中央更改图片,以便首先看到您的程序的用户了解它的作用和要求。


作者Man已保存

最简单的主循环


我们将主循环添加到程序中,这将使程序正常运行,直到用户希望退出(并以可访问的形式通知程序有关程序),而不是像上一课中那样是固定的延迟。 这是这种循环的大致结构:

while (!quit) //   ,  : { //       //  -   } 


SDL事件队列


为了正确使用SDL事件系统,我们至少需要对其功能有最少的了解。 当SDL从操作系统接收到一个事件时,它将在较早接收到但尚未从程序中提取的所有其他事件之后,将其放置在队列的末尾。 如果在启动程序之后,我们将交替改变窗口的大小,单击窗口并单击一个键,则事件队列将如下所示:


当我们调用SDL_PollEvent时,我们从队列的开头获取一个事件,这是其余事件中最早的一个。 使用SDL_PollEvent从队列中接收事件会将其从那里删除,为避免这种情况,您可以使用SDL_PeepEvents函数并设置SDL_PEEKEVENT标志来“监听”该事件。 您可以在文档中阅读有关此功能的更多信息,本文的框架中并不需要(而且您很可能也会),因此将不考虑该功能。

事件处理


在主循环中,我们希望接收绘制前一帧之后发生的所有可用事件,并对其进行处理。 为此,只需将SDL_PollEvent置于while循环中即可,因为如果接收到该事件,它将返回1,如果没有接收到该事件,则将返回0。 由于该程序所做的全部工作都是在某些事件上完成的,因此使用布尔变量(布尔退出)就足够了,它指示我们是否要结束该程序,并在收到这些事件时将其值设置为true。

 // e -    SDL_Event,       while (SDL_PollEvent(&e)) { //      if (e.type == SDL_QUIT) { quit = true; } //       if (e.type == SDL_KEYDOWN) { quit = true; } //     if (e.type == SDL_MOUSEBUTTONDOWN) { quit = true; } } 


该循环应放置在应用程序的主循环内。
当用户关闭窗口时,将发生SDL_QUIT类型的事件;在键盘上按下键时,将发生SDL_KEYDOWN类型的事件(在按住该键时会发生很多很多次,类似于在打印文本时按住键时如何重复字母);而当用户关闭窗口时,发生SDL_MOUSEBUTTONDOWN类型的事件。鼠标单击。 这些只是您的应用程序可以接收的一些事件-当然,SDL总共可以接收20种以上类型的事件,本文当然无法涵盖,因此,您应该在SDL_Event文档中阅读它们

主周期完成


我们已经完成了事件处理,但是在主循环中,缺少了另一部分-场景显示。 在上一课程中,我们已经考虑了该主题,仅是应用此知识而已,其主要周期将采用以下形式:

 //   SDL_Event e; //   bool quit = false; while (!quit) { //   while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { quit = true; } if (e.type == SDL_KEYDOWN) { quit = true; } if (e.type == SDL_MOUSEBUTTONDOWN) { quit = true; } } //   SDL_RenderClear(renderer); renderTexture(image, renderer, x, y); SDL_RenderPresent(renderer); } 


该程序将永远有效。 好吧,或者至少直到用户有礼貌地要求她停止为止。 启动程序后,使用叉形按钮,键盘上的任何键或单击窗口内的鼠标都可以完成程序。 直到那一刻,她将不断重绘窗口的内容。

转换程序的补充:程序形式的程序很可能会消耗所有可用的处理器资源,从而完全加载一个内核。 在主周期末尾使用SDL_Delay添加一个小的延迟(1-5 ms)是合理的,这样,在没有事件的情况下,程序可以将处理器释放给其他程序。 这不适用于已经需要所有可用资源的沉重游戏,当以100fps的速度每秒花100毫秒等待是一种不允许的奢侈时。

第四课结束


因此,下一课结束了。 在第5课中与大家见面:从纹理图集采样

作业:尝试添加图像移动,例如,使用箭头。

Source: https://habr.com/ru/post/zh-CN437308/


All Articles