2015/11/2用Python写游戏,pygame入门(2):游戏中的事件和显示

时间:2021-08-06 03:30:14

pygame是一个比较大的库,以我这点弱小的实力是没办法详解的。所以我只讲我懂得那些部分,其他部分由大家慢慢查找了解。

-------------------------------

我用pygame的目标很明确,写一个自己的游戏娱乐,权当学习时的放松。一个小项目的运行是非常有成就感的,所以一切讲解都按这样的简单步骤来。

首先,我们来理解动画:

2015/11/2用Python写游戏,pygame入门(2):游戏中的事件和显示

上面是一种给孩子玩的小游戏,将几张不同姿态的图片放在一个转轴上,旋转转轴时我们就能看到一个连贯的飞翔动画,几张断开的静止的图像,当我们以高速切换时,人眼就会认为是连续的动作。这就是视觉暂留效应的体现。根据这种原理,人类发明了电影。

1824年,英国伦敦大学教授皮特.马克.罗葛特在他的研究报告《移动物体的视觉暂留现象》中最先提出视觉暂留或者“余晖”效应
人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”。
一般来说,视觉暂留会停留0.1-0.4秒左右,当然这因人而异。电影业开始时认为24帧(一秒钟24张图)的图像就可以让所有的人都察觉不到异常,成为真正的动图。当然,随着现在技术的发展,电影的帧率是高于这个值的。在游戏业的实验中,为了摆脱卡顿感,我们一般是使用30~40帧的图像速率,这是因为游戏的图像是离散的,并不是连续的,所以需要更高的帧率来提高体验,帧率一般是越高越平滑,但超过100帧以后变化就不明显了。
游戏的过程其实就是一个动画的过程,与单纯的动画不一样的是,我们还加入了玩家对画面的反馈。也就是事件。
反馈是通过输入设备完成的,如鼠标、键盘、手柄等等,每个设备有相应的反馈信息,比如说鼠标移动,按键按下,松开。这些事都在pygame里成为了基础的事件,可以直接使用。
接下来我通过一个例子来说明基础的动画和事件:
# -*- coding: utf8 -*-

background_image_filename = 'sky.jpg'
mouse_image_filename = 'cloud.png'
#指定图像文件名称 import pygame #导入pygame库
from sys import exit #向sys模块借一个exit函数用来退出程序 pygame.init() #初始化pygame,为使用硬件做准备
screen = pygame.display.set_mode((600, 450), 0, 32)
#创建了一个窗口
pygame.display.set_caption("Hello, World!")
#设置窗口标题 background = pygame.image.load(background_image_filename).convert()
mouse_cursor = pygame.image.load(mouse_image_filename).convert_alpha()
#加载并转换图像
while True:
#游戏主循环 for event in pygame.event.get():
if event.type == pygame.QUIT:
#接收到退出事件后退出程序
pygame.quit()
exit() screen.blit(background, (0,0))
#将背景图画上去 x, y = pygame.mouse.get_pos()
#获得鼠标位置
x-= mouse_cursor.get_width() / 2
y-= mouse_cursor.get_height() / 2
#计算光标的左上角位置
screen.blit(mouse_cursor, (x, y))
#把光标画上去 pygame.display.update()
#刷新一下画面

运行结果是这样的:

2015/11/2用Python写游戏,pygame入门(2):游戏中的事件和显示

当鼠标在屏内移动时,云也会跟着移动,当然这朵云是我临时抠的,实在是很违和。。大家略过这一点。

大家先看主循环里的

while True:
#游戏主循环
...
screen.blit(background, (0,0))
#将背景图画上去
...
screen.blit(mouse_cursor, (x, y))
#把光标画上去
pygame.display.update()
#刷新画面

把不需要的东西省略掉,先看这几句。在主循环里,我们一次次地执行下面三句代码的操作。就是先画背景图,再花光标图,然后刷新画面。每次因为光标发生了变化,它就每次画出不同的图像,所以这就变成了动画,也就能实时显示,也就是我上面说的部分。

那么,事件呢?

看这段代码:

    for event in pygame.event.get():
if event.type == pygame.QUIT:
#接收到退出事件后退出程序
pygame.quit()
exit()

这是一段事件响应代码,pygame.event.get()方法会接受所有程序中发生的事件。当判断这个事件是一个关闭程序(QUIT)的事件时,就将程序关闭。

那么有哪些事件呢?

事件 产生途径 参数
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

这里有很多事件,我们当然是不用把它背下来的,这里只是一个说明。之后在font模块时,我将写一个可以显示所有你得到的事件的程序。

再详细说明上述代码

background_image_filename = 'sky.jpg'

这句是简单的字符串赋值语句,只是为了之后使用时能更简单地理解名称的意义。

screen = pygame.display.set_mode((600, 450), 0, 32)

这一句使用了pygame.display.set_mode((640, 450), 0, 32)这一句是创建一个窗口,第一个参数是一个元组,用于传递窗口的大小,第二个参数是窗口的模式,默认可以写0,第三个参数为色深,一般写32就行。

set_mode()返回一个Surface对象,之后可以对这个对象操作。

第二个参数有如下使用:

标志位 功能
FULLSCREEN 创建一个全屏窗口
DOUBLEBUF 创建一个“双缓冲”窗口,建议在HWSURFACE或者OPENGL时使用
HWSURFACE 创建一个硬件加速的窗口,必须和FULLSCREEN同时使用
OPENGL 创建一个OPENGL渲染的窗口
RESIZABLE 创建一个可以改变大小的窗口
NOFRAME 创建一个没有边框的窗口

大家可以自己使用看看效果。

background = pygame.image.load(background_image_filename).convert()

convert()可以把图像数据都转化为Surface对象,每次加载完图像以后就应该做这件事件(事实上因为它太常用了,如果你不写pygame也会帮你做);convert_alpha相比convert,保留了Alpha 通道信息(可以简单理解为透明的部分),这样我们的光标才可以是不规则的形状。

blit()是个重要函数,第一个参数为一个Surface对象,第二个为左上角位置。将第一个对象画到相应的位置上。

但是画完还没有用,必须把画完以后的图像用update()显示在屏幕上,否则画面一片漆黑。