Python编写微信打飞机小游戏(二)
最后更新于:2022-04-01 14:22:53
通过之前的准备,已经成功加载了程序资源并使得程序能够顺利运行,接下来开始编写我方小飞机的模块。在工程目录下创建一个名为myplane.py的文件,导入pygame模块(注意文件编码问题)
1、精灵
Pygame中所有移动对象都可看做是一个精灵(sprite),精灵之间能够进行相互的交互通信,例如碰撞检测等等,对于pygame模块中精灵的介绍网上有很多资源,例如[《Pygame之精灵》](http://www.cnblogs.com/xiaowuyi/archive/2012/06/26/2563990.html "Pygame之精灵")在这里我方飞机就是一个精灵对象,因此其类定义应继承于pygame的精灵类:
~~~
class MyPlane(pygame.sprite.Sprite):
~~~
2、myplane的初始化
游戏运行的第一步就是生成我方飞机。我方飞机在生成时需要给定一些具体参数,如飞机的形状、飞机的生成位置,这些都属于myplane类的成员变量(Python是一门面向对象的变成语言)。Python对成员变量的初始化都是在__init__(self)函数中完成的,类似于C++语言中的构造函数,其中self则形如一个显式的this指针,代表当前类的一个抽象对象。init()函数的具体形式如下:
~~~
def __init__(self, bg_size):
pygame.sprite.Sprite.__init__(self)
self.image1 = pygame.image.load("image/hero1.png") # 加载飞机图片1
self.rect = self.image1.get_rect() # 得到当前我方飞机的位置
self.width, self.height = bg_size[0], bg_size[1] # 本地化背景图片的尺寸
self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60) # 定义飞机初始化位置,底部预留60像素
self.speed = 10 # 设置飞机移动速度
~~~
首先在初始化时需要先调用基类(pygame.sprite.Sprite)的init()函数。注意由于在确定飞机的初始化位置时需要知道当前背景的尺寸,因此通过形参bg_size将当前背景尺寸传进来(为了方便,转换成width和height两个变量),然后是加载我方飞机的图片,并通过image的成员函数get_rect()得到我方飞机的图片尺寸。在指定飞机位置时,只需要对飞机这个精灵对象的rect属性进行设置,rect有许多有趣的属性(center、topmid等),在此只需指定其left(左边框坐标)和top(顶部边框坐标)来实现图片位置的定位,注意需要在底部预留一段空白区域(此处为60个像素)。最后,指定我方飞机的移动速度,这里暂时设置为10,稍后用到。
3、定义我方飞机移动函数
在对我方飞机完成初始化之后,需要定义飞机的移动操作,通过WASD或者上下左右键实现对飞机的控制。以向上移动(move_up()函数)为例,代码如下:
~~~
def move_up(self): # 飞机向上移动的操作函数,其余移动函数方法类似
if self.rect.top > 0: # 如果飞机尚未移动出背景区域
self.rect.top -= self.speed
else: # 若即将移动出背景区域,则及时纠正为背景边缘位置
self.rect.top = 0
~~~
对飞机的移动是通过将对应边框坐标加减speed来完成的,例如向上移动的话就是self.rect.top - self.speed,注意此处需要对飞机当前的位置进行越界检测,如果此时self.rect.to<0了,即说明飞机已经超出图像的上界,即将top值置为零,即如论在如何向上移动,飞机都只停留在北京的上边缘。其余三个方向的移动函数原理类似,这里不再赘述:
~~~
def move_down(self):
if self.rect.bottom < self.height - 60:
self.rect.top += self.speed
else:
self.rect.bottom = self.height - 60
def move_left(self):
if self.rect.left > 0:
self.rect.left -= self.speed
else:
self.rect.left = 0
def move_right(self):
if self.rect.right < self.width:
self.rect.right += self.speed
else:
self.rect.right = self.width
~~~
4、在主函数mian中实例化我方飞机
在初步编写好我方飞机模块myplane.py之后,需要在主程序中进行实例化,以显示我方灵活的小飞机。首先在主程序中加载我方飞机模块:
~~~
import myplane
~~~
然后在mian()函数中完成飞机的实例化操作:
~~~
me = myplane.MyPlane(bg_size) # 生成我方飞机
~~~
强调由于整个程序运行只需要进行一次实例化,因此应将此操作放在main()函数中的whlie循环之外。在实例化完成后,需要将我方飞机绘制到屏幕上进行显示:
~~~
screen.blit(me.image1, me.rect)
~~~
注意由于飞机是实时移动的,需要在每帧图像中都对飞机进行重新绘制,因此绘制飞机的blit()操作应该写在main()函数的while循环之内
5、检测用户按键消息并控制飞机移动
在控制飞机移动时需要响应用户的鼠标键盘事件。这里介绍Pygame中两种事件响应机制,一是形如“for event in pygame.event.get():”的形式,只需要验证“event.type”的键值即可得到当前用户发出的事件类型,这种消息处理机制适合处理偶然发生的事件,如用户的暂停操作、关闭操作等。另外一种则是下面将要用到的“pygame.key.get_pressed()”,这种形式下会将指定类型的用户操作保存为一个列表,只需判断列表中对应时间消息的标志位的真假即可判断某类时间是否发生,适合处理频繁出现的事件操作(如键盘的方向控制事件),详情如下:
~~~
key_pressed = pygame.key.get_pressed() # 获得用户所有的键盘输入序列
if key_pressed[K_w] or key_pressed[K_UP]: # 如果用户通过键盘发出“向上”的指令,其他类似
me.move_up()
if key_pressed[K_s] or key_pressed[K_DOWN]:
me.move_down()
if key_pressed[K_a] or key_pressed[K_LEFT]:
me.move_left()
if key_pressed[K_d] or key_pressed[K_RIGHT]:
me.move_right()
~~~
当然,这些操作应该放置在while循环内部,因为这是一个实时检测实时刷新的过程。到此我们的程序的基本框架就完成了,循环播放背景音乐,小飞机能够灵活控制移动(不会越界),但我方小飞机还不会喷气、不会发生子弹,这些功能我们在下一篇博文中再介绍吧。