python实例:利用pygame实现小游戏“飞机大战”


0、程序代码

代码1:

  1 import random
  2 import pygame
  3 
  4 # 屏幕大小的常量
  5 SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
  6 # 刷新的帧率
  7 FRAME_PER_SEC = 60
  8 # 创建敌机的定时器常量
  9 CREATE_ENEMY_EVENT = pygame.USEREVENT
 10 # 英雄发射子弹事件
 11 HERO_FIRE_EVENT = pygame.USEREVENT+1
 12 #子弹速度
 13 BULLET_SPEED = -2.5
 14 
 15 
 16 class GameSprite(pygame.sprite.Sprite):
 17     """"飞机大战游戏精灵"""
 18 
 19     def __init__(self, image_name, speed = 1):
 20         # 调用父亲的初始化方法
 21         super().__init__()
 22         # 定义对象的属性
 23         self.image = pygame.image.load(image_name)
 24         self.rect = self.image.get_rect()
 25         self.speed = speed
 26 
 27     def update(self):
 28         #在屏幕的垂直方向上移动
 29         self.rect.y += self.speed
 30 
 31 
 32 class Background(GameSprite):
 33     """"游戏背景精灵"""
 34 
 35     def __init__(self, is_alt = False):
 36         # 1.调用父类构造方法
 37         super().__init__("./images/background.png")
 38         # 2.判断是否与前图像循环重合,若否,则需重新设置初始位置
 39         if is_alt:
 40             self.rect.y = -self.rect.height
 41 
 42 
 43     def update(self):
 44         # 1.调用父类的方法,,,注意super后面要加括号!!!
 45         super().update()
 46         # 2.判断是否移出屏幕
 47         if self.rect.y >= SCREEN_RECT.height:
 48             self.rect.y = -self.rect.height
 49 
 50 
 51 class Enemy(GameSprite):
 52     """"敌机精灵"""
 53 
 54     def __init__(self):
 55         # 1.调用父类方法,创建敌机精灵
 56         super().__init__("./images/enemy1.png")
 57         # 2. 指定敌机的初始随机速度 1-2-3
 58         self.speed = random.randint(1,3)
 59         # 3.指定敌机的初始随机位置
 60         self.rect.bottom = 0
 61 
 62         max_x = SCREEN_RECT.width - self.rect.width
 63         self.rect.x = random.randint(0, max_x)
 64 
 65 
 66     def update(self):
 67 
 68         # 1.调用父类方法,保持垂直方向的飞行
 69         super().update()
 70         # 2.判断是否非出屏幕,如果是,需要从精灵组删除敌机
 71         if self.rect.y >= SCREEN_RECT.height:
 72             #print("飞出屏幕,需要从精灵组删除...")
 73             # kill方法可以将精灵从精灵组中移除
 74             self.kill()
 75 
 76     def __del__(self):
 77         #print("敌机挂了%s" %self.rect)
 78         pass
 79 
 80 
 81 class Hero(GameSprite):
 82     """英雄精灵"""
 83 
 84     def __init__(self):
 85         # 1.调用父类方法,设置image和speed
 86         super().__init__("./images/me1.png", speed = 0)
 87         self.speed1 = 0
 88         # 2.设置英雄的初始位置
 89         self.rect.centerx = SCREEN_RECT.centerx
 90         self.rect.bottom = SCREEN_RECT.bottom - 100
 91         # 3.创建子弹精灵组
 92         self.bullets = pygame.sprite.Group()
 93 
 94     def update(self):
 95         #(错误的判断句,会导致一旦出界就很难再恢复回来)if 0 <= self.rect.x <= SCREEN_RECT.width - self.rect.width:
 96         self.rect.x += self.speed
 97         if self.rect.x < 0:
 98             self.rect.x = 0
 99         elif self.rect.right > SCREEN_RECT.width:
100             self.rect.right = SCREEN_RECT.width
101 
102         self.rect.y += self.speed1
103         if self.rect.y < 0:
104             self.rect.y = 0
105         elif self.rect.bottom > SCREEN_RECT.height:
106             self.rect.bottom = SCREEN_RECT.height
107 
108 
109     def fire(self):
110         #print("发射子弹")
111         # 1.创建子弹精灵
112         bullet = Bullet()
113         # 2.设置精灵位置
114         bullet.rect.bottom = self.rect.y
115         bullet.rect.centerx = self.rect.centerx
116         # 3.将精灵添加到精灵组
117         self.bullets.add(bullet)
118 
119 
120 class Bullet(GameSprite):
121     """"子弹精灵"""
122 
123     def __init__(self):
124         # 调用父类方法
125         super().__init__("./images/bullet1.png", BULLET_SPEED)
126 
127     def update(self):
128         super().update()
129         if self.rect.bottom < 0:
130             self.kill()
131 
132     def __del__(self):
133         #print("子弹被销毁")
134         pass
View Code

代码2:

  1 from plane_sprites import *
  2 # 游戏主程序
  3 
  4 class PlaneGame(object):
  5     """"飞机大战主游戏"""
  6 
  7     def __init__(self):
  8         print("游戏初始化")
  9 
 10         # 1.创建游戏的窗口
 11         self.screen = pygame.display.set_mode(SCREEN_RECT.size)
 12         # 2.创建游戏的时钟
 13         self.clock = pygame.time.Clock()
 14         # 3.调用私有方法,精灵和精灵组的创建
 15         self.__create_sprites()
 16         # 4.设置定时器事件——创建敌机 1s
 17         pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)
 18         pygame.time.set_timer(HERO_FIRE_EVENT, 300)
 19 
 20     def __create_sprites(self):
 21         # 创建背景精灵和精灵组
 22         bg1 = Background()
 23         bg2 = Background(True)
 24         self.back_group = pygame.sprite.Group(bg1, bg2)
 25         # 创建敌机精灵
 26         self.enemy_group = pygame.sprite.Group()
 27         # 创建英雄精灵
 28         self.hero = Hero()
 29         self.hero_group = pygame.sprite.Group(self.hero)
 30 
 31 
 32     def start_game(self):
 33         print("游戏开始...")
 34 
 35         while True:
 36             # 1.设置刷新帧率
 37             self.clock.tick(FRAME_PER_SEC)
 38             # 2.事件监听
 39             self.__event_handler()
 40             # 3.碰撞检测
 41             self.__check_collide()
 42             # 4.更新/绘制精灵组
 43             self.__update_sprites()
 44             # 5.更新显示
 45             pygame.display.update()
 46 
 47 
 48     def __event_handler(self):
 49         for event in pygame.event.get():
 50             #判断是否退出游戏
 51             if event.type == pygame.QUIT:
 52                 PlaneGame.__game_over()
 53             elif event.type == CREATE_ENEMY_EVENT:
 54                 #print("敌机出现。。。")
 55                 # 创建敌机精灵
 56                 enemy = Enemy()
 57                 # 将敌机精灵添加到敌机精灵组中
 58                 self.enemy_group.add(enemy)
 59             elif event.type == HERO_FIRE_EVENT:
 60                 self.hero.fire()
 61 
 62             # elif event.type == pygame.KEYDOWN and event.key == pygame. K_RIGHT:
 63             #     print("向右移动")
 64 
 65         # 使用键盘提供的方法获得按键元组
 66         keys_pressed = pygame.key.get_pressed()
 67         #判断元组中对应的按键索引值
 68         if keys_pressed[pygame.K_RIGHT]:
 69             self.hero.speed = 2
 70         elif keys_pressed[pygame.K_LEFT]:
 71             self.hero.speed = -2
 72         elif keys_pressed[pygame.K_DOWN]:
 73             self.hero.speed1 = 2
 74         elif keys_pressed[pygame.K_UP]:
 75             self.hero.speed1 = -2
 76         else:
 77             self.hero.speed = 0
 78             self.hero.speed1 = 0
 79 
 80 
 81     def __check_collide(self):
 82         # 1.子弹摧毁敌机
 83         pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
 84         # 2.敌机撞毁英雄
 85         enenmy = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
 86         if len(enenmy) > 0:
 87             self.hero.kill()
 88             print("飞机被撞毁,任务失败!")
 89             PlaneGame.__game_over()
 90 
 91     def __update_sprites(self):
 92         # 更新显示背景
 93         self.back_group.update()
 94         self.back_group.draw(self.screen)
 95         # 更新显示敌机
 96         self.enemy_group.update()
 97         self.enemy_group.draw(self.screen)
 98         # 更新显示英雄
 99         self.hero_group.update()
100         self.hero_group.draw(self.screen)
101         # 更新显示子弹
102         self.hero.bullets.update()
103         self.hero.bullets.draw(self.screen)
104 
105     @staticmethod
106     def __game_over():
107         print("游戏结束")
108 
109         pygame.quit()
110         exit()
111 
112 if __name__ == '__main__':
113     #创建游戏对象
114     game = PlaneGame()
115     #启动游戏
116     game.start_game()
View Code

最终呈现结果:

 

 

1、准备工作

1.1 图像素材

为了实现这个游戏,我们需要一些图片(png格式)。其中包括:玩家飞机、敌机、背景图等等。

        

 

1.2 打开pycharm,导入pygame包

pygame是python中一个第三方库,具有良好的游戏开发性能,功能强大且内容十分丰富,具体请百度或者参考该博客: https://blog.csdn.net/qq_38526635/article/details/82688786

 

1.3 pygame绘制游戏窗口

1) pygame中的坐标系以左上角为原点,提供了一个类pygame.Rect用于描述矩形区域.

Rect对象的常见属性:x, y, left, top, bottom, right, center, centerx, centery, size, width, height.

1 Rect(x, y, width, height) →Rect

 

2)pygame.display用于创建与管理窗口

1 # 创建游戏主窗口
2 screen = pygame.display.set_mode((480, 700))

 

3)图像绘制

 1 import pygame
 2 
 3 游戏初始化标准句,Rect对象可以不用
 4 pygame.init()
 5 
 6 # 创建游戏的窗口 480 * 700
 7 screen = pygame.display.set_mode((480, 700))
 8 
 9 # 绘制背景图像
10 bg = pygame.image.load("./images/background.png")
11 screen.blit(bg, (0, 0))
12 # pygame.display.update()
13 
14 # 绘制英雄的飞机
15 hero = pygame.image.load("./images/me1.png")
16 screen.blit(hero, (150, 300))
17 
18 # 可以在所有绘制工作完成之后,统一调用update方法
19 pygame.display.update()
20 
21 while True:
22     pass
23 
24 pygame.quit()
View Code

 

1.4 游戏循环

 

 1)pygame.time.Clock用于刷新帧率

  要使用时钟对象需要两步:①在游戏初始化创建一个时钟对象;②在游戏循环中让时钟对象调用tick(帧率)方法

2)pygame.event.get()可以得到用户当前所做动作的时间列表(代码相对比较固定)

 1 #游戏循环
 2 while True:
 3     #设置帧率
 4     clock.tick(60)
 5     #事件监听
 6     for event in pygame.event.get():
 7         #判断用户是否点击了关闭按钮
 8         if event.type == pygame.QUIT:
 9             print("退出游戏。。。")
10             pygame.quit()
11             #直接退出系统
12             exit()
View Code

 

2、游戏初始化

该游戏的大体框架是两部分内容:一部分是基于pygame.sprite.Sprite这个父类,创建各种各样的派生类,比如子弹类,敌机类。第二部分是创建主程序类PlaneGame,使用前面各种类来实现具体的游戏功能。

首先先来看类PlaneGame的创建过程:

2.1  创建类PlaneGame的构造函数

1 class PlaneGame(object):
2 
3     def __init__(self):
4         print("游戏初始化")

2.2 创建游戏的窗口

1 # 屏幕大小的常量
2 SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
3 ...
4         self.screen = pygame.display.set_mode(SCREEN_RECT.size)

2.3创建游戏时钟

1         self.clock = pygame.time.Clock()

2.4调用私有方法,精灵和精灵组的创建

1         self.__create_sprites()

2.5设置定时器事件

 1 # 创建敌机的定时器常量
 2 CREATE_ENEMY_EVENT = pygame.USEREVENT
 3 # 英雄发射子弹事件
 4 HERO_FIRE_EVENT = pygame.USEREVENT+1
 5 
 6 class PlaneGame(object):
 7     def __init__(self):
 8 ...
 9         pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)
10         pygame.time.set_timer(HERO_FIRE_EVENT, 300)
View Code

 

3、创建精灵组

3.1创建精灵父类GameSprite

继承自pygame.sprite.Sprite类,包含image、rect、spped=1等属性和update()方法。

 1 class GameSprite(pygame.sprite.Sprite):
 2 
 3     def __init__(self, image_name, speed = 1):
 4         # 调用父亲的初始化方法
 5         super().__init__()
 6         # 定义对象的属性
 7         self.image = pygame.image.load(image_name)
 8         self.rect = self.image.get_rect()
 9         self.speed = speed
10 
11     def update(self):
12         #在屏幕的垂直方向上移动
13         self.rect.y += self.speed
View Code

3.2 创建游戏背景精灵类

采用一张图循环拼接构成游戏背景,故需要在主程序中生成两个背景精灵对象。

 1 class Background(GameSprite):
 2 
 3     def __init__(self, is_alt = False):
 4         # 1.调用父类构造方法
 5         super().__init__("./images/background.png")
 6         # 2.判断是否与前图像循环重合,若否,则需重新设置初始位置
 7         if is_alt:
 8             self.rect.y = -self.rect.height
 9 
10 
11     def update(self):
12         # 1.调用父类的方法,,,注意super后面要加括号!!!
13         super().update()
14         # 2.判断是否移出屏幕
15         if self.rect.y >= SCREEN_RECT.height:
16             self.rect.y = -self.rect.height
View Code

3.3  创建敌机精灵类

其实质是一秒产生一架敌机并将其随机从上方某处以1,2或者3的速度落下。当飞出屏幕外注意使用self.kill()自我销毁。

 1 class Enemy(GameSprite):
 2 
 3     def __init__(self):
 4         # 1.调用父类方法,创建敌机精灵
 5         super().__init__("./images/enemy1.png")
 6         # 2. 指定敌机的初始随机速度 1-2-3
 7         self.speed = random.randint(1,3)
 8         # 3.指定敌机的初始随机位置
 9         self.rect.bottom = 0
10 
11         max_x = SCREEN_RECT.width - self.rect.width
12         self.rect.x = random.randint(0, max_x)
13 
14 
15     def update(self):
16 
17         # 1.调用父类方法,保持垂直方向的飞行
18         super().update()
19         # 2.判断是否非出屏幕,如果是,需要从精灵组删除敌机
20         if self.rect.y >= SCREEN_RECT.height:
21             #print("飞出屏幕,需要从精灵组删除...")
22             # kill方法可以将精灵从精灵组中移除
23             self.kill()
24 
25     def __del__(self):
26         #print("敌机挂了%s" %self.rect)
27         pass
View Code

3.4 创建子弹类

子弹类飞出屏幕外需要自我销毁

 1 class Bullet(GameSprite):
 2 
 3     def __init__(self):
 4         # 调用父类方法
 5         super().__init__("./images/bullet1.png", BULLET_SPEED)
 6 
 7     def update(self):
 8         super().update()
 9         if self.rect.bottom < 0:
10             self.kill()
11 
12     def __del__(self):
13         #print("子弹被销毁")
14         pass
View Code

3.5 创建英雄类

英雄类多了一个fire()方法,并且内部包含子弹类

 1 class Hero(GameSprite):
 2 
 3     def __init__(self):
 4         # 1.调用父类方法,设置image和speed
 5         super().__init__("./images/me1.png", speed = 0)
 6         self.speed1 = 0
 7         # 2.设置英雄的初始位置
 8         self.rect.centerx = SCREEN_RECT.centerx
 9         self.rect.bottom = SCREEN_RECT.bottom - 100
10         # 3.创建子弹精灵组
11         self.bullets = pygame.sprite.Group()
12 
13     def update(self):
14         #(错误的判断句,会导致一旦出界就很难再恢复回来)if 0 <= self.rect.x <= SCREEN_RECT.width - self.rect.width:
15         self.rect.x += self.speed
16         if self.rect.x < 0:
17             self.rect.x = 0
18         elif self.rect.right > SCREEN_RECT.width:
19             self.rect.right = SCREEN_RECT.width
20 
21         self.rect.y += self.speed1
22         if self.rect.y < 0:
23             self.rect.y = 0
24         elif self.rect.bottom > SCREEN_RECT.height:
25             self.rect.bottom = SCREEN_RECT.height
26 
27 
28     def fire(self):
29         #print("发射子弹")
30         # 1.创建子弹精灵
31         bullet = Bullet()
32         # 2.设置精灵位置
33         bullet.rect.bottom = self.rect.y
34         bullet.rect.centerx = self.rect.centerx
35         # 3.将精灵添加到精灵组
36         self.bullets.add(bullet)
View Code

3.6 在主程序中创建精灵(组)

 1 class PlaneGame(object):
 2 
 3     def __init__(self):
 4 ...
 5 
 6     def __create_sprites(self):
 7         # 创建背景精灵和精灵组
 8         bg1 = Background()
 9         bg2 = Background(True)
10         self.back_group = pygame.sprite.Group(bg1, bg2)
11         # 创建敌机精灵
12         self.enemy_group = pygame.sprite.Group()
13         # 创建英雄精灵
14         self.hero = Hero()
15         self.hero_group = pygame.sprite.Group(self.hero)
View Code

 

4、开始游戏

首先令FRAME_PER_SEC = 60,调用self.clock.tick(FRAME_PER_SER)设置帧率为60

 1 class PlaneGame(object):
 2     def __init__(self):
 3 ...
 4 
 5     def __create_sprites(self):
 6 ...
 7 
 8     def start_game(self):
 9         while True:
10             # 1.设置刷新帧率
11             self.clock.tick(FRAME_PER_SEC)
12             # 2.事件监听
13             self.__event_handler()
14             # 3.碰撞检测
15             self.__check_collide()
16             # 4.更新/绘制精灵组
17             self.__update_sprites()
18             # 5.更新显示
19             pygame.display.update()
View Code

4.1 事件监听

 1     def __event_handler(self):
 2         for event in pygame.event.get():
 3             #判断是否退出游戏
 4             if event.type == pygame.QUIT:
 5                 PlaneGame.__game_over()
 6             elif event.type == CREATE_ENEMY_EVENT:
 7                 #print("敌机出现。。。")
 8                 # 创建敌机精灵
 9                 enemy = Enemy()
10                 # 将敌机精灵添加到敌机精灵组中
11                 self.enemy_group.add(enemy)
12             elif event.type == HERO_FIRE_EVENT:
13                 self.hero.fire()
14 
15         # 使用键盘提供的方法获得按键元组
16         keys_pressed = pygame.key.get_pressed()
17         #判断元组中对应的按键索引值
18         if keys_pressed[pygame.K_RIGHT]:
19             self.hero.speed = 2
20         elif keys_pressed[pygame.K_LEFT]:
21             self.hero.speed = -2
22         elif keys_pressed[pygame.K_DOWN]:
23             self.hero.speed1 = 2
24         elif keys_pressed[pygame.K_UP]:
25             self.hero.speed1 = -2
26         else:
27             self.hero.speed = 0
28             self.hero.speed1 = 0
View Code

 具体参考pygame.event.get()方法使用

4.2  碰撞检测

pygame.sprite.groupcollide()用于两个精灵群的碰撞

pygame.sprite.spritecollide()用于精灵和精灵群的碰撞

 1     def __check_collide(self):
 2 
 3         # 1.子弹摧毁敌机
 4         pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
 5 
 6         # 2.敌机撞毁英雄
 7         enenmy = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
 8         if len(enenmy) > 0:
 9             self.hero.kill()
10             print("飞机被撞毁,任务失败!")
11             PlaneGame.__game_over()
View Code

4.3 更新/绘制精灵组

 1     def __update_sprites(self):
 2         # 更新显示背景
 3         self.back_group.update()
 4         self.back_group.draw(self.screen)
 5         # 更新显示敌机
 6         self.enemy_group.update()
 7         self.enemy_group.draw(self.screen)
 8         # 更新显示英雄
 9         self.hero_group.update()
10         self.hero_group.draw(self.screen)
11         # 更新显示子弹
12         self.hero.bullets.update()
13         self.hero.bullets.draw(self.screen)
View Code

4.4 显示

1             pygame.display.update()

5、启动与结束游戏

 1 class PlaneGame(object):
 2 ...
 3     @staticmethod
 4     def __game_over():
 5         print("游戏结束")
 6 
 7         pygame.quit()
 8         exit()
 9 
10 if __name__ == '__main__':
11     #创建游戏对象
12     game = PlaneGame()
13     #启动游戏
14     game.start_game()
View Code

 6、游戏优化

本程序所实现的游戏还较为粗糙,可以继续优化。其方向包括但不限于:增加音效,增加飞机爆炸画面,击杀敌机增加积分模式等等。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM