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