Python之pygame,从入门到精通(二)
上次我们试着写了一个最简单的Pygame程序并且解释了一个大概的框架,这次就Pygame中也是游戏中最关键的事件来展开。
理解事件
事件是什么,其实从名称来看我们久能想到些什么,而且你所想到的基本就是事件的真正意思了。我们上一个程序,会一直运行下去,知道你关闭窗口而产生一个QUIT事件,Pygame会接受用户的各种操作(比如按键盘,移动鼠标等)产生事件。事件随时可能发生,而且量也可能会很大,Pygame的做法是把一系列的事件存放一个队列里,逐个的处理。
事件检索
上个程序中,使用了pygame.event.get()来处理所有的事件,这好像打开大门让所有的人进入。如果我们使用pygame.event.wait(),Pygame就会等到发生一个事件才继续下去,就好像有哨兵把守的门一样,来一个进一个…一般游戏中不太实用,因为游戏往往是需要动态运作的;而另一个方法pygame.event.poll()就好一些,一旦调用,它会根据现在的情形返回一个真实的事件,或者一个“什么都没有”。下表是一个常用事件集:
事件 | 产生途径 | 参数 |
---|---|---|
QUIT | 用户按下关闭按钮 | none |
ATIVEEVENT | Pygame被激活或者隐藏 | gain, state |
KEYDOWN | 键盘被按下 | unicode, key, mod |
KEYUP | 键盘被放开 | key, mod |
MOUSEMOTION | 鼠标移动 | pos, rel, buttons |
MOUSEBUTTONDOWN | 鼠标按下 | pos, button |
MOUSEBUTTONUP | 鼠标放开 | pos, button |
JOYAXISMOTION | 游戏手柄(Joystick or pad)移动 | joy, axis, value |
JOYBALLMOTION | 游戏球(Joy ball)移动 | joy, axis, value |
JOYHATMOTION | 游戏手柄(Joystick)移动 | joy, axis, value |
JOYBUTTONDOWN | 游戏手柄按下 | joy, button |
JOYBUTTONUP | 游戏手柄放开 | joy, button |
VIDEORESIZE | Pygame窗口缩放 | size, w, h |
VIDEOEXPOSE | Pygame窗口部分公开(expose) | none |
USEREVENT | 触发了一个用户事件 | code |
下面我们写一个把所有方法输出的一段代码,它的结果是这样的:
我们这里使用了wait(),因为这个程序在有事件发生的时候动弹就可以了。还用了font模块来显示文字,下面是源代码:
import pygame
from pygame.locals import *
from sys import exit
from random import randint
SCREEN_SIZE = (640, 480)
pygame.init()
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
font = pygame.font.SysFont("arial", 16)
font_height = font.get_linesize()
event_text = []
while True:
event = pygame.event.wait()
event_text.append(str(event))
event_text = event_text[-SCREEN_SIZE[1]/font_height:]
if event.type == QUIT:
exit()
screen.fill((255, 255, 255))
y = SCREEN_SIZE[1]-font_height
for text in event_text:
screen.blit(font.render(text, True, (randint(0, 255), randint(0, 255), randint(0, 255))), (0, y))
y -= font_height
pygame.display.update()
处理鼠标事件
MOUSEMOTION事件会在鼠标动作时发生,它有三个参数:
- buttons:一个含有三个数字的元组,三个值分别代表左键、中键和右键,1就是按下了。
- pos:鼠标光标的位置
- rel:代表了现在距离上次产生鼠标事件时的距离
和MOUSEMOTION类似的,我们还有MOUSEBUTTONDOWN和MOUSEBUTTONUP两个事件,看名字就知道什么意思了。很多时候,你只需要知道鼠标点下就可以了,那就可以不用上面那个比较强大(也比较复杂)的事件了。它们的参数为:
- button:看清楚了少了个s,这个值代表了哪个按键被操作
- pos:鼠标光标的位置
处理键盘事件
键盘和游戏手柄的事件比较类似,为KEYDOWN和KEYUP,下面有一个例子来演示使用方向键移动一些东西。
# _*_coding:utf-8_*_
import pygame
from pygame.locals import *
from sys import exit
background_image_file = 'sea.jpg'
pygame.init()
pygame.display.set_caption('move')
screen = pygame.display.set_mode((640, 480), 0, 32)
background = pygame.image.load(background_image_file).convert()
x, y = 0, 0
move_x, move_y = 0, 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
exit()
if event.type == KEYDOWN:
if event.key == K_LEFT:
move_x = -1
elif event.key == K_RIGHT:
move_x = 1
elif event.key == K_UP:
move_y = -1
elif event.key == K_DOWN:
move_y = 1
elif event.type == KEYUP:
move_x = 0
move_y = 0
# 计算出新的坐标
x += move_x
y += move_y
screen.fill((0, 0, 0))
screen.blit(background, (x, y))
# 在新的位置上画图
pygame.display.update()
KEYDOWN和KEYUP的参数秒速如下:
- key -按下或者放开的键值,是一个数字,估计地球上很少有人可以记住,所以Pygame中你可以使用K_xxx来表示,比如字母a就是K_a,还有K_SPACE和K_RETURN等。
- mod -包含了组合键信息,如果mod & KMOD_CTRL是真值,表示用户同时按下了Ctrl键。类似的还有KMOD_SHIFT,KMOD_ALT。
- unicode -代表了按下键的Unicode值,这个自行google。
事件过滤
并不是所有的事件都需要处理的,就好像不是所有登门造访的人都是我们欢迎的一样。比如,俄罗斯方块就无视你的鼠标,而在游戏场景切换的时候,你按什么都是徒劳的。我们应该有一个方法来过滤掉一些我们不感兴趣的事件(当然我们可以不处理这些没兴趣的事件,但最好的方法还是让它们根本不进入我们的事件队列),我们使用pygame.event.set_blocked(事件名)来完成。如果有好多事件需要过滤,可以传递一个列表,比如pygame.event.set_blocked([KEYDOWN, KEYUP]),如果你设置参数None,那么所有的事件都被打开了。与之相对的,我们使用pygame.event,set_allowed()来设定允许的事件。
产生事件
通常玩家做什么,Pygame就产生对应的事件就可以了,不过有的时候我们西药模拟出一些事件来,不如录像回放的时候,我们就要把用户的操作再现一遍。
为了产生事件,必须先造一个出来,然后再传递它:
# _*_coding:utf-8_*_
import pygame
from pygame.locals import *
me_event = pygame.event.Event(KEYDOWN, {"key": K_SPACE, "mod": 0, "unicode": u''})
pygame.event.post(me_event)