SDL 2课:第3课-事件

大家好! 这是SDL 2中的第三课。信息来自来源。 我不喜欢Lasy Foo事件处理教程,所以我会自己编写,但是可以在这里这里找到资料。

我们开始,欢迎上课

大事记


今天,我们将教我们的程序在约翰的帮助下应对事件。

因此,让我们开始吧。 连接SDL 2并创建3个全局变量和2个常量。

#include <SDL2/SDL.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; 

接下来,我们编写上一课中已经知道的3个函数:

初始化
 int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } 

负荷
 int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } 

退出
 int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } 


注意(!),如果您复制上一课的代码,请不要忘记将微笑改为john

应该说的一切:我决定在初始化和图像加载阶段显示错误。

因此,让我们继续。 打开main并调用InitLoad函数。

 int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } } 

现在,让我们看看任何应用程序如何工作。 您运行的任何程序(Google Chrome,Paint,Minecraft)都具有运行大量次的主循环。 这对于动态性是必要的。 以前,我们编写了一个仅显示2秒钟微笑的程序,但是为了使该程序学习如何响应用户的操作(或至少无休止地显示图像),它需要一个While循环。

它会不断重复,并且在其中我们已经可以做我们想要的事情,例如处理事件。 但是在开始胶质循环之前,让我们创建一些变量。

  bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; 

现在,我们将分析所有内容。 首先,创建一个boolean类型的运行变量。 该变量负责执行循环:程序运行时,它为true ,如果我们要停止执行,则将该变量设置为false 。 接下来,创建类SDL_Evente对象。 该对象的属性将包含接收到的事件的数据,将更加详细。 之后,我们创建SDL_Rect类的对象r 。 这是绘制带有我们所需坐标的对象所需的矩形。 然后我们创建int类型的变量xy 。 立即将其值分配为零。 这些将是我们角色的坐标。 下一项,我们分别给变量rxry赋值xyrxry是矩形r的坐标。

现在是时候打开主循环了。

  while (run) { while(SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } 

让我们分析一下这段代码。 我们有两个周期。 如前所述,第一个主要对象是主要对象,它通过运行变量工作。 第二个循环负责处理事件。

SDL_PollEvent()函数打开一次执行主循环时接收到的事件队列,删除最后一个事件,并将有关此事件的数据写入传递给此函数的对象的变量中,即为e 。 如果已删除队列中的所有事件,此函数将返回0, NULLfalse ,因此我们编写while条件(SDL_PollEvent(&e)!= NULL)

我们进一步看:我们要做的第一步是单击窗口框架中的十字。 如果单击它,那么将为对象e类型变量分配值SDL_QUIT 。 如果发生这种情况,则将false赋给运行变量,然后循环结束。

接下来,我编写了一个键盘击键测试。 如果按下按钮,则e.type变量等于SDL_KEYDOWN 。 接下来,检查键值。 变量e.key.keysym.sym存储按钮的值。 我们将此值与所需值进行比较,并执行某些操作。 我们将更改约翰的坐标。 如果按下向上箭头,则y减小1,如果向下箭头,则增大y ,依此类推。

处理完事件后,重新分配rxry以更新Man的坐标。 接下来,我们编写已经熟悉的函数SDL_FilRect ,它的作用非常大。 如果我们没有编写,那么约翰在移动时会留下难看的痕迹,因此,每一帧我们都会绘制一个白色背景,并在其上方绘制一个精灵。 之后,我们使用SDL_BlitSurface函数绘制英雄。 在这里,我们将使用矩形r或其变量xy不仅在左上角绘制,还要绘制一些必要的坐标。 接下来,只需更新窗口。

在主循环之后,写return quit(); 完成程序。

仅此而已,本课结束了。 这是这样的代码:

代号
 #include <SDL2/SDL.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *john = NULL; int init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init: " << SDL_GetError() << std::endl; system("pause"); return 1; } win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; system("pause"); return 1; } scr = SDL_GetWindowSurface(win); return 0; } int load() { john = SDL_LoadBMP("john.bmp"); if (john == NULL) { std::cout << "Can't load image: " << SDL_GetError() << std::endl; system("pause"); return 1; } return 0; } int quit() { SDL_FreeSurface(john); SDL_DestroyWindow(win); SDL_Quit(); return 0; } int main (int argc, char ** args) { if (init() == 1) { return 1; } if (load() == 1) { return 1; } bool run = true; SDL_Event e; SDL_Rect r; int x = 0; int y = 0; rx = x; ry = y; while (run) { while(SDL_PollEvent(&e) != NULL) { if (e.type == SDL_QUIT) { run = false; } if (e.type == SDL_KEYDOWN) { if (e.key.keysym.sym == SDLK_UP) { y -= 1; } if (e.key.keysym.sym == SDLK_DOWN) { y += 1; } if (e.key.keysym.sym == SDLK_RIGHT) { x += 1; } if (e.key.keysym.sym == SDLK_LEFT) { x -= 1; } } } rx = x; ry = y; SDL_FillRect(scr, NULL, SDL_MapRGB(scr -> format, 255, 255, 255)); SDL_BlitSurface(john, NULL, scr, &r); SDL_UpdateWindowSurface(win); } return quit(); } 


我跟你说再见,再见!

<<上一课|| 下一课>>

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


All Articles