【python游戏编程之旅】第三篇---pygame事件与设备轮询

本系列博客介绍以python+pygame库进行小游戏的开发。有写的不对之处还望各位海涵。

在上一篇博客中,我们学习了pygame中的IO、数据http://www.cnblogs.com/msxh/p/4973003.html。

这次我们来一起了解一下pygame事件与设备轮询。

一、pygame事件

1.简介

pygame事件可以处理游戏中的各种事情。其实在前两节的博客中,我们已经使用过他们了。如下是pygame的完整事件列表:

QUIT,ACTIVEEVENT,KEYDOWN,KEYDOWN,MOUSEMOTION,MOUSEBUTTONUP,MOUSEBUTTONDOWN,JOYAXISMOTION,

JOYBALLMOTION,JOYHATMOTION........

更多的事件可以去查pygame的文档。http://www.pygame.org/docs/index.html

查看pygame的文档是一种非常好的学习方式。

2.实时事件循环

pygame中的事件处理是放在一个实时的循环中来完成的。将代码都放在一个while True的循环中,但是这样会造成死循环,所以在里面加一句sys.exit()来退出。

for event in pygame.event.get()

上面的代码将会创建当前等待处理的事件的一个列表,然后使用for循环来遍历里面的事件。这样,我们将会根据事件产生的顺序依次地进行不同的操作。常见的事件是按键按下,按键释放以及鼠标移动。通常需要最先处理QUIT事件(在用户关闭窗口的时候会产生该事件。)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()        

3.键盘事件

键盘事件包括最典型的keyup 和 keydown 当按键按下的时候响应KEYDOWN事件,按键弹起的时候响应KEYDOWN事件。通常可以设置一个事件变量,然后根据keyup或者keydown给它赋不同的值。

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == KEYDOWN:
            key_flag = True
        elif event.type == KEYUP:
            key_flag = False

默认的话pygame不会重复地去响应一个被一直按住的键,只是在按键第一次被按下的时候响应一次,如果需要重复响应一个按键的话下面的操作:

pygame.key.set_repeat(10)
#参数是一个以毫秒为单位的值

4.鼠标事件

pygame支持一些鼠标事件,他们包括MOUSEMOTION,MOUSEBUTTONUP,MOUSEBUTTONDOWN.

在MOUSEMOTION中包含了一些属性:event.pos,event.rel,event.buttons

 for event in pygame.event.get():
        if event.type == MOUSEMOTION:
             mouse_x,mouse_y = event.pos
             move_x,move_y = event.rel

MOUSEBUTTONDOWN里面的属性:

event.type == MOUSEBUTTONDOWN:
            mouse_down = event.button
            mouse_down_x,mouse_down_y = event.pos

MOUSEBUTTONUP里面的属性:

event.type == MOUSEBUTTONUP:
            mouse_up = event.button
            mouse_up_x,mouse_up_y = event.pos

二、设备轮询

在pygame中除了pygame事件,还可以使用设备轮询的方法来检测是否有事件发生。而且在python里面是没有switch语句的,因此当需要处理的事件过多时,我们肯定不会去一条一条的去写if...elif....else来匹配,而设备轮询正好解决了这个棘手的问题。

1.轮询键盘

在pygame中,使用pygame.key.get_pressed()来轮询键盘接口。这个方法会返回布尔值的一个列表,其中每个键一个标志。使用键常量值来匹配按键,这样的好处就是不必遍历事件系统就可以检测多个键的按下。例如:

keys = pygame.key.get_pressed()

if keys[K_ESCAPE]:

   pygame.quit()

        sys.exit()

我们可以设计一个打字测速小游戏来综合练习一下键盘的轮询:

 1 import sys, random, time, pygame
 2 from pygame.locals import *
 3 
 4 def print_text(font, x, y, text, color=(255,255,255)):
 5     imgText = font.render(text, True, color)
 6     screen.blit(imgText, (x,y))
 7     
 8 
 9 #主程序
10 pygame.init()
11 screen = pygame.display.set_mode((600,500))
12 pygame.display.set_caption("Keyboard Demo")
13 font1 = pygame.font.Font(None, 24)
14 font2 = pygame.font.Font(None, 200)
15 white = 255,255,255
16 yellow = 255,255,0
17 color = 125,100,210
18 
19 key_flag = False
20 correct_answer = 97 
21 seconds = 10
22 score = 0
23 clock_start = 0
24 game_over = True
25 
26 while True:
27     for event in pygame.event.get():
28         if event.type == QUIT:
29             pygame.quit()
30             sys.exit()
31         elif event.type == KEYDOWN:
32             key_flag = True
33         elif event.type == KEYUP:
34             key_flag = False
35 
36     keys = pygame.key.get_pressed()
37     if keys[K_ESCAPE]:
38         sys.exit()
39 
40     if keys[K_RETURN]:
41         if game_over:
42             game_over = False
43             score = 0
44             seconds = 11
45             clock_start = time.clock()
46 
47     current = time.clock() - clock_start
48     speed = score * 6
49     if seconds-current < 0:
50         game_over = True
51     elif current <= 10:
52         if keys[correct_answer]:
53             correct_answer = random.randint(97,122)
54             score += 1
55 
56  
57     #清屏
58     screen.fill(color)
59 
60     print_text(font1, 0, 20, "Try to keep up for 10 seconds...")
61 
62     if key_flag:
63         print_text(font1, 450, 0, "you are keying...")
64 
65     if not game_over:
66         print_text(font1, 0, 80, "Time: " + str(int(seconds-current)))
67 
68     print_text(font1, 0, 100, "Speed: " + str(speed) + " letters/min")
69 
70     if game_over:
71         print_text(font1, 0, 160, "Press Enter to start...")
72 
73     print_text(font2, 0, 240, chr(correct_answer-32), yellow)
74 
75     
76     #更新
77     pygame.display.update()
78 
79     

在这个程序中,我们使用到了一些新的模块和函数,让我们来了解一下。

Random.randint(x,y);看名字知道这个函数的作用了,它可以返回一个x~y之间的随机数。

另外一个模块是time。time.clock()函数会返回从程序启动到现在为止的时间。

2.轮询鼠标

同样,我们可以使用类似的方法去轮询鼠标事件。

这里有3个相关的函数:

(1)pygame.mouse.get_pos(),这个函数会返回鼠标当前的坐标x,y;

(2)pygame.mouse.get_rel();

rel_x ,rel_y = pygame.mouse.get_rel().利用这个函数可以读取鼠标的相对移动。

(3)btn_one,btn_two,btn_three = pygame.mouse.get_pressed();

利用这个函数,可以获取鼠标按钮的状态。比如当左键按下的时候btn_one 的值会被赋值为1,鼠标按键弹起是会被赋值为0。

同样我们可以设计一个小案例来熟悉一下鼠标轮询,比如当鼠标按下的时候 打印鼠标按的是左键还是右键,鼠标点击的位置,鼠标当前的坐标等等。这里就不给出实现代码了,感兴趣的可以自己实现一下。

下个博客中我们将会一起学习如何在pygame中加载位图,以及pygame中一些常用的数学函数。并且还会综合前几次学到的知识制作一个小游戏。游戏效果图如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏九彩拼盘的叨叨叨

学习纲要:异步流程处理

修改上面的代码,用 Promise,async/await,事件发布订阅 这几种方式实现下面的需求

10220
来自专栏数据星河

如何对第一个Vue.js组件进行单元测试 (下)

       让我们来写首个测试。我们首先需要使用shallowMount手动挂载我们的组件,并将其存储在我们将执行断言的变量中。我们还可以通过propsDat...

18100
来自专栏AhDung

【手记】.net正则行尾匹配符$的问题

本来想用正则Split一下sql语句中简单场景的的GO,于是用^GO$(配合忽略大小写和多行模式),可居然连这种情况都搞不掂:

17240
来自专栏Seebug漏洞平台

HCTF2017 部分 Web 出题思路详解

11月12日结束的HCTF2017,我总共出了其中4道题目,这4道题目涵盖了我这半年来接触的很多有趣的东西。下面就简单讲讲出题思路以及完整的Writeup。

39790
来自专栏落影的专栏

iOS开发笔记(六)

前言 专注、坚持,是优良的品格。 正文 1、cell和cell.contentView 的区别 在给UITableViewCell添加视图的时候,我们有以下两种...

34750
来自专栏听雨堂

从MapX到MapXtreme2004[1]-工具选择

  网上的MapXtreme的资料实在太少了,MapXtreme编程基本上只能靠英文帮助和以前的Mapx的一些底子。我想写一个系列,把Mapx到Mapxtrem...

235100
来自专栏华章科技

这件神器,每个 Python 学习者都值得一试

Jupyter Notebook 是一款 Web 应用,它能让用户将上面说的各种窗口里的东西,全部组合到一个可读性好,易于共享,且对新手友好的文档中。这个文档里...

9920
来自专栏python小白到大牛

这件神器,每个 Python 学习者都值得一试

不论你是刚开始学 Python,还是正在啃数据分析的骨头,对你来说,不断在各种命令行窗口和编辑器里切来切去,或者不断打开各种窗口查看 matplotlib 的输...

15940
来自专栏腾讯NEXT学位

Vue.js最佳实践(五招让你成为Vue.js大师)

61870
来自专栏申龙斌的程序人生

零基础学编程036:快速编写一个GUI程序

在《零基础学编程035:群发邮件并不难》里,我们学会了发邮件,我用于向shenlongbin@sync.omnigroup.com发送一封邮件,就可以实现GTD...

44680

扫码关注云+社区

领取腾讯云代金券