500行代碼,教你用python寫個微信飛機大戰

  • 2019 年 10 月 16 日
  • 筆記

在這裡插入圖片描述

這幾天在重溫微信小遊戲的飛機大戰,玩着玩着就在思考人生了,這飛機大戰怎麼就可以做的那麼好,操作簡單,簡單上手。

幫助蹲廁族、YP族、飯圈女孩在無聊之餘可以有一樣東西讓他們振作起來!讓他們的左手 / 右手有節奏有韻律的朝着同一個方向來回移動起來!

這是史詩級的發明,是濃墨重彩的一筆,是……
在一陣抽搐後,我結束了遊戲,瞬時覺得一切都索然無味,正在我進入賢者模式時,突然想到,如果我可以讓更多人已不同的方式體會到這種美輪美奐的感覺豈不美哉?

所以我打開電腦,創建了一個 plan_game.py……

先看效果圖

在這裡插入圖片描述

操作環境

  • 操作系統:windows10
  • python版本:python 3.7
  • 代碼編輯器:pycharm 2018.2
  • 使用模塊:os,sys,random,pygame

因為實現代碼使用到了一個pygame的第三方模塊,沒有的先 pip install 一下,這裡順便提供一個比較好的pygame的教程.

https://eyehere.net/2011/python-pygame-novice-professional-index/

具體實現

  1. 首先我們先指定素材文件的文件目錄.方便我們後面的使用。這些素材已經全部上傳至公眾號Python專欄,後台回復:飛機大戰,即可獲得。
import os    # 得到當前文件夾下面的material_images目錄的路徑  source_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'material_images')
  1. 實現一個Game類,用來完成這個遊戲的主要邏輯。
import pygame      class Game():      def __init__(self, background_image_path, size=(480, 700), title='飛機大戰', font_name='方正舒體', font_size=30, speed=2000):          '''          :param background_image_path: 背景圖片的路徑地址          :param size: 遊戲窗口的大小          :param title: 遊戲窗口的標題          :param font_name: 指定字體          :param font_size: 指定字體大小          :param speed: 背景圖滾動整個窗口一次所用時間,單位為ms          '''          self.size = size          self.screen = pygame.display.set_mode(size)          self.title = title          self.background_image_path = background_image_path          self.background = pygame.image.load(self.background_image_path).convert()          # 設置字體對象,得到系統中自帶的字體          self.font = pygame.font.SysFont(font_name, font_size)          # 得到Clock對象,我們可以使用它來獲取距離上次繪製圖像的時間          self.clock = pygame.time.Clock()          # 背景圖初始位置          self.height = 0          # 使用窗口的高度處於滾動的時間,就能得到每ms滾動的距離          self.every_ms_move_distance = self.size[1] / speed   # 2秒          # 分數          self.score = 0          # 存放所有的敵機          self.enemies = []          def show_score(self):          '''          顯示分數, 在窗口的的最上方距離上邊距10px, 左右居中          '''          pass          def set_time_passed(self):          # 控制畫 的幀, 越大越快          # 得到上一次繪製圖像到到現在的時間, ms          self.time_passed = self.clock.tick()          def draw_background(self):          '''          繪製背景圖片,一直向下滾動,營造飛機一直往上面飛的感覺          '''          # 每次移動的距離 = 每ms移動的距離 * 上次到現在的時間(ms)          pass          def create_enemy(self, image_path=os.path.join(source_dir,'enemy1.png'), enemy_number=5):          '''          創建敵機          :param image_path: 敵機的圖片地址          :param enemy_number: 最多有幾個敵機在屏幕上          '''          pass          def draw_enemies(self, time_passed, screen):          '''          繪製敵機到屏幕上,清理跑出窗口的敵機,          :param time_passed: 上次繪製導向現在經過的時間          :param screen: 繪製的窗口對象          '''          pass          def bullet_and_enemy_crash_detection(self, bullets):          '''          檢測子彈是否擊中敵機          :param bullets: 飛機的所有子彈          '''          pass          def plan_and_enemy_crash_detection(self, plan, allow_crash_size=None):          '''          檢測敵機與飛機是否相撞          :param plan: 飛機對象          :param allow_crash_size: 允許飛機碰撞的大小,只有左右有效          '''          pass          def draw_plan(self, plan, time_passed):          '''          繪製飛機          :param plan: 飛機對象          :param time_passed: 距離上次繪製的時間          :return:          '''          pass          def game_over(self):          '''          遊戲結束          '''          while True:              # 繪製背景圖              pass          def run(self):          '''          遊戲入口函數,開始函數,主體函數          :return:          '''            # 設置遊戲窗口的大小          pygame.display.set_caption(self.title)          # 初始化一個飛機對象          plan = Plan()            while True:              # 如果飛機自毀完成, 遊戲結束, 調用game_over函數              pass                # 檢測監聽事件              pass                # 檢測上下左右的移動案件.              # w,a,s,d 和 上,下,左,右鍵都可以              # 然後執行plan.update函數,改變飛機的位置              pass                # 子彈和敵機的碰撞檢測              self.bullet_and_enemy_crash_detection(plan.bullets)              # 飛機與敵機的碰撞檢測              self.plan_and_enemy_crash_detection(plan)              # 設置屬性time_passed的值, 距離上次的時間,方便後面使用              self.set_time_passed()              # 繪製背景圖片              self.draw_background()              # 顯示分數              self.show_score()              # 生成敵機              self.create_enemy()              # 繪製敵機              self.draw_enemies(time_passed=self.time_passed, screen=self.screen)              # 繪製飛機              self.draw_plan(plan=plan, time_passed=self.time_passed)              # 繪製子彈              plan.draw_bullets(time_passed=self.time_passed, screen=self.screen)              # 顯示我們的圖像              pygame.display.update()    這裡說以下怎樣查看自己的系統中有哪些自帶的字體.  pygame.font.get_fonts(),這個函數就能夠得到系統中所有的自帶字體文件。不過,當我們遊戲中有中文的時候,我們也得選擇支持中文的字體,否則的話是顯示不出中文的。

在這裡插入圖片描述

  1. 實現DestroyAnimationMixin類,這個類主要是用來顯示飛機或敵機的自毀動畫
# 顯示飛機自毀動畫的Mixin類, 可用于飛機和敵機的自毀動畫顯示  class DestroyAnimationMixin():        def show_destroy_animation(self, time_passed, destroy_time=200):          '''          顯示自毀動畫          動畫其實就是幾張圖片切換的比較快,我們的眼睛識別不出來,所以認為他是動態的,也就是動畫          :param time_passed: 距離上次繪製圖像到現在的時間,單位ms          :param destroy_time: 自毀動畫總共顯示時間,單位ms          '''            # 因為我們的自毀圖片有四張,需要依次顯示,首先動畫的效果          # self.destroy_image_position 表示第幾章自毀圖片,從零開始          # 如果大於等於4了,說明自毀動畫顯示完成,設置self.destroyed變量為True, 方便別處調用          if self.destroy_image_position >= 4:              self.destroyed = True              return            # 依次加載自毀圖片          if self.time_passed >= destroy_time / 4:              self.image = pygame.image.load(os.path.join(source_dir, self.destroy_images[self.destroy_image_position])).convert_alpha()              self.destroy_image_position += 1              self.time_passed = 0          else:              self.time_passed += time_passed

在這裡插入圖片描述

  1. 實現飛機類,完成飛機的主要操作。飛機的操作包括:飛機位置、飛機子彈、發射子彈等。
# 飛機類,繼承DestroyAnimationMixin, 方便使用顯示自毀動畫的函數  class Plan(DestroyAnimationMixin):      def __init__(self, image_path=os.path.join(source_dir,'plan.png'), background_size=(480, 700)):          '''          :param image_path: 飛機圖片地址          :param background_size: 遊戲窗口大小          '''          self.background_size = background_size          self.image = pygame.image.load(image_path).convert_alpha()          self.image_size = self.image.get_size()          self.position = [(background_size[0]-self.image_size[0]) / 2, 500]          # 飛機每次移動的距離          self.every_time_move_distance = 0.5          # 飛機的子彈          self.bullets = []          # destroy association attributes, 自毀相關屬性          # 開始自毀          self.start_destroy = False          # 自毀結束          self.destroyed = False          # 自毀圖片          self.destroy_images = ['me_destroy_1.png', 'me_destroy_2.png', 'me_destroy_3.png', 'me_destroy_4.png']          # 自毀圖片位置          self.destroy_image_position = 0          # 距離上次繪製圖像到現在的時間          self.time_passed = 0        def update(self, direction):          '''          更新飛機位置          :param direction: 飛機移動方向          '''          pass        def shut(self, image_path=os.path.join(source_dir,'bullet.png')):          '''          飛機發射子彈          :param image_path: 子彈圖片          '''          pass        def draw_bullets(self, time_passed, screen):          '''          繪製飛機的所有子彈          :param time_passed: 距離上次繪製圖像到現在的時間          :param screen: 繪製到哪一個窗口中          '''          pass

在這裡插入圖片描述

  1. 實現敵機類,完成敵機的主要操作。主要是用來更新位置。
# 敵機類,繼承DestroyAnimationMixin, 方便使用顯示自毀動畫的函數  class Enemy(DestroyAnimationMixin):      def __init__(self, image_path=os.path.join(source_dir, 'enemy1.png'), speed=2000, background_size=(480, 700)):          '''          :param image_path: 敵機圖片地址          :param speed: 敵機移動整個窗口需要的時間,單位ms,也就是速度          :param background_size: 遊戲窗口的尺寸          '''          self.image = pygame.image.load(image_path).convert_alpha()          self.speed = background_size[1] / speed          self.background_size = background_size          self.position = [random.randint(0, background_size[0]-self.image.get_size()[0]), -self.image.get_size()[1]]          # 開始自毀          self.start_destroy = False          # 自毀完成          self.destroyed = False          # 自毀圖片路徑          self.destroy_images = ['enemy1_down1.png', 'enemy1_down2.png', 'enemy1_down3.png', 'enemy1_down3.png']          # 距離上次繪製圖像到現在的時間          self.time_passed = 0          # 自毀圖片在self.destroy_images的位置          self.destroy_image_position = 0        def update(self, time_passed):          '''          更新敵機的位置          :param time_passed: 距離上次繪製圖像到現在的時間          :return:          '''          pass
  1. 實現子彈類,完成子彈的主要操作
# 飛機子彈類  class Bullet():      def __init__(self, image_path=os.path.join(source_dir,'bullet.png'), background_size=(480, 700), plan=None, speed=1000):          '''          :param image_path: 子彈的圖片地址          :param background_size: 遊戲窗口大小          :param plan: 飛機對象          :param speed: 子彈飛行速度          '''          self.image = pygame.image.load(image_path).convert_alpha()          self.background_size = background_size          self.speed = background_size[1] / speed          # 子彈是否擊中敵機          self.destroyed = False          self.position = self._get_position(plan)        def _get_position(self, plan):          '''          根據plan得到子彈發出位置          :param plan: 飛機對象          '''          bullet_size = self.image.get_size()          plan_width = plan.image_size[0]          x = (plan_width-bullet_size[0]) / 2          return [plan.position[0] + x, plan.position[1]]        def update(self, time_passed):          '''          改變子彈位置          :param time_passed: 距離上次繪製圖像到現在的時間          '''          # 如果子彈超出屏幕或者擊中敵機,就設置self.position[1]為-100,在plan.draw的時候就移除它          if self.position[1] + self.image.get_size()[1] <= 0 or self.destroyed:              self.position[1] = -100              return            # 改變的距離 = 時間 * 速率          self.position[1] -= time_passed * self.speed

在這裡插入圖片描述

這樣,我們就把所有的操作都實現完了,接下來只需要使用 Game().run(),就可以運行我們的遊戲了。

關注公眾號:Python專欄,後台回復:飛機大戰,即可獲得完整代碼及素材包。