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
代碼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()
最終呈現結果:

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()
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()
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)
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
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
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
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
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)
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)
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()
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
具體參考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()
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)
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()
6、游戲優化
本程序所實現的游戲還較為粗糙,可以繼續優化。其方向包括但不限於:增加音效,增加飛機爆炸畫面,擊殺敵機增加積分模式等等。
