實戰項目:飛機大戰

實戰項目:飛機大戰

項目目標:

實現基本的飛機大戰python

項目描述:

運行程序,英雄飛機出如今屏幕底邊的中央區域,飛機中央每隔一秒會自動發射一枚子彈。隨着遊戲的開始,敵機會在屏幕上方隨機不定時的出如今屏幕內向下飛行。英雄飛機須要經過移位躲避敵機或用子彈消滅敵機,避免碰撞致使遊戲結束。編程


項目實現環境:

  • 編輯器:vscode編輯器微信

  • 操縱系統:win10dom

  • 編輯語言:python3.7編輯器

項目中所使用的庫或模塊:

  • pygame:第三方模塊,用於編寫遊戲ide

  • random:python自帶的模塊,在指定的數字範圍內隨機產生相應結果動畫

項目需求:

  • 繪製遊戲背景圖並實現背景圖滾動ui

  • 繪製敵機並實現出現的時間隨機spa

  • 繪製英雄飛機,並實現上下左右移動.net

  • 實現英雄飛機自動發射子彈

  • 實現英雄飛機與敵機、子彈與敵機的碰撞檢測

項目準備:建立文件

  • 建立專門調用功能實現飛機大戰的主文件main.py

  • 建立爲飛機大戰提供功能的類文件tools.py,包含的內容有:

    • 精靈類

    • 背景類

    • 敵機類

    • 子彈類

    • 英雄飛機類

代碼編寫

如何建立屏幕

# 導入第三方模塊
import pygame
# 導入pygame庫中的全部模塊並進行初始化
pygame.init()

# 建立屏幕,設置屏幕大小(應根據背景圖大小設置)
surface = pygame.display.set_mode((480,580))

# 卸載全部模塊,退出程序
pygame.quit()

以上代碼必須寫入,不然沒法正常運行


如何導入圖片,建立圖片對象

image = pygame.image.load('圖片的地址')


如何將圖片繪製到屏幕上

surface.blit(image,(0,0))
  • 第一個參數爲圖片對象

  • 第二個參數爲繪製的初始位置


如何更新屏幕

pygame.display.update()

每次繪製完全部圖片後必定要更新屏幕


如何建立精靈組

group = pygame.sprite.Group(精靈1對象,精靈2對象)


精靈組的三個方法

# 同時調用精靈組中全部精靈的update方法
group.update()
# 同時繪製精靈組中全部精靈的位置,須要傳入屏幕對象
group.draw(屏幕對象)
# 向精靈組中添加精靈的方法
group.add(精靈)


如何碰撞檢測

# 精靈組與精靈組之間的碰撞檢測,好比子彈與敵機之間
pygame.sprite.groupcollide('精靈組1','精靈組2',True,True)

# 精靈與精靈組之間的碰撞檢測,好比敵機與英雄飛機
pygame.sprite.spritecollide('精靈','精靈組',True)

其中,True表明碰撞的精靈或精靈組內的精靈會消失


編寫tools.py文件代碼


常量部分

# 480\580是圖片的寬高

SCREEN = pygame.Rect(0,0,480,580)

# 建立敵機事件
CREAT_EVENT = pygame.USEREVENT
# 發射子彈事件
FIRE_BULLET = pygame.USEREVENT+1

pygame.Rect能夠用來描述矩形區域,從左到右的參數分別表明 x、y、矩形區域的寬、矩形區域的高

pygame.USEREVENT表明定時事件的編號,經過後面+一、+二、+3.....的方式添加多個事件


編寫精靈類

# 精靈類
class SpriteParent(pygame.sprite.Sprite):
    def __init__(self,imgae,speed=1)
        super().__init__()
        self.image = pygame.image.load(image)
        self.rect = self.image.get_rect()
        self.speed = speed
       
    def update(self):
        self.rect.y += self.speed
  • 該類繼承了精靈類,須要包含兩種方法:初始化方法和update()方法。

  • 在初始化方法中要添加三個屬性,分別是:加載的圖片對象、圖片的矩形區域,圖片的移動速度。其中圖片的矩形區域能夠使用圖片對象的 get_rect() 來獲取,速度自定義設置,這裏設置成 每次移動1像素。

  • 這裏要注意的是,咱們是擴展父類的初始化方法,而不是重寫父類的初始化方法

  • update()方法的做用是更新圖片的位置

  • self.rect.y 表明矩形區域在y軸的位置


編寫背景類

class BackGround(SpriteParent):

   def __init__(self,is_alt=False):
       super().__init__('./images/background.png')
       # 若是is_alt爲True,則設置圖片的初始位置爲圖片高度的負值
       if is_alt:
           self.rect.y = -self.rect.height
           
   def update(self):
       # 繼承父類的update方法,使圖片每次向下移動1像素
       super().update()
       # 當圖片頂部的位置等於屏幕的高度時,將該圖片返回到屏幕上方,與上方圖片進行銜接
       if self.rect.y >= SCREEN.height:
           self.rect.y = -self.rect.height

要實現背景圖片循環上下交替滾動,因此須要實例化兩個背景圖片對象,其中一個對象的初始位置位於y軸的負方向,且y爲背景圖片的高度的負值


編寫敵機類

import random
class Enemy(SpriteParent):
    def __init__(self):
         super().__init__('./images/enemy.png')
         max_x = SCREEN.width - self.rect.width
         # 設置敵機在x軸隨機出現的範圍
         self.rect.x = random.randint(0,max_x)
         # 固定敵機在y軸出現的位置
         self.rect.y = -self.rect.height

   

    def update(self):

        super().update()
       # 若是敵機飛出屏幕,則殺死該敵機對象,而後會自動調用__del__方法將其從內存中刪除
        if self.rect.y >= SCREEN.height:
             self.kill()
           
   def __del__(self):
       print("敵機已經從內存中銷燬..")


編寫子彈類

class Bullet(SpriteParent):
    def __init__(self):
        super().__init__('./images/bullet.png')

   

    def update(self):

        self.rect.y -= self.speed
         if self.rect.y <= -self.rect.height:
             self.kill()
           
     def __del__(self):
         print("子彈已經從內存中銷燬...")


編寫英雄飛機類

class Hero(SpriteParent):
     def __init__(self):
         super().__init__('./images/hero1.png')
         # centerx表明矩形區域在x軸的中心位置
         # 這裏設置英雄飛機的初始位置爲屏幕底端位於x軸的中間
         self.rect.centerx = SCREEN.rect.centerx
         self.rect.y = SCREEN.rect.height - self.rect.height
         self.bullet_group = pygame.sprite.Goup()
   
     def update(self):
         # 獲取從鍵盤上按下的值
          key_down = pygame.key.get_pressed()
         # 判斷按下的值,向對應的方向移動
         # 內部是設置英雄飛機上下左右移動的邊界
         if key_down[pygame.K_DOWN]:
             if self.rect.bottom >= SCREEN.height:
                 self.rect.bottom = SCREEN.height
             self.rect.y += 2
         elif key_down[pygame.K_UP]:
             if self.rect.y <= 0:
                 self.rect.y = 0
             self.rect.y -= 2
         elif key_down[pygame.K_LEFT]:
             if self.rect.x <= 0:
                 self.rect.x = 0
             self.rect.x -= 2
         elif key_down[pygame.K_RIGHT]:
             if self.rect.right >= SCREEN.width:
                 self.rect.right = SCREEN.width
             self.rect.x += 2
               
    def fire(self):
       bullet = Bullet()
       # 設置子彈出現的初始位置
       bullet.rect.centerx = self.rect.centerx
       bullet.rect.y = self.rect.y-20
       # 向子彈精靈組中添加子彈精靈
       self.bullet_group.add(bullet)
       


編寫main.py文件

from tools import *
import pygame

class PlaneGame(object):
     def __init__(self):
         pygame.init()
         self.surface = pygame.display.set_mode(0,0,SCREEN.size)
         # 設置遊戲時鐘對象
         self.clock = pygame.time.Clock()
         self.__create_sprite()
         # 設置定時建立敵機和發射子彈的定時器,1000表明1s
         # 第一個參數爲事件編號,第二個參數是定時的時間
         pygame.time.set_timer(CREAT_EVENT,1000)
         pygame.time.set_timer(FIRE_BULLET,1000)
       
     def __create_sprite(self):
         bg1 = Background()
         bg2 = Backgroud(True)
         self.bg_group = pygame.sprite.Group(bg1,bg2)
       
         self.enemy_group = pygame.sprite.Group()
       
         self.hero = Hero()
         self.hero_group = pygame.sprite.Group(self.hero)
       
     def startGame(self):
          # 循環表明遊戲開始
          while True:
             # 設置屏幕刷新頻率爲每秒更新60次,這種頻率足以使動畫流暢運行
              self.clock.tick(60)
              self.__event_handler()
              self.__check_collide()
              self.__update_sprites()
           # 每次繪製完就要更新一次
           pygame.display.update()
           
     def __event_handler(self):
          # 獲取屏幕事件
         for event in pygame.event.get():
             # 若是點擊屏幕的退出按鈕,則結束遊戲
             if event.type == pygame.QUIT:
                 PlaneGame.gemeover()
             # 定時建立敵機
             elif event.type == CREAT_EVENT:
                 enemy = Enemy()
                 self.enemy_group.add(enemy)
             # 定時發射子彈,實現自動射擊的效果
             elif event.type == FIRE_BULLET:
                 self.hero.fire()

               

    def __check_collide(self):

       

       '''碰撞檢測'''

        pygame.sprite.groupcollide(self.enemy_group,self.hero.bullet_group,True,True)

         # 精靈與精靈組內的精靈產生碰撞,會返回與精靈碰撞的精靈對象
         enemies = pygame.sprite.spritecollide(self.hero,self.enemy_group,True)
         # 若是enemies有值,說明敵機與英雄飛機產生碰撞,那麼殺死英雄飛機,遊戲結束
        if enemies:
            self.hero.kill()
             PlaneGame.gemeover()

           

    def __update_sprites(self):

       # 更新和繪製精靈組中全部精靈的位置
        self.bg_group.update()
         self.bg_group.draw(self.surface)
       
         self.enemy_group.update()
         self.enemy_group.draw(self.surface)
       
         self.hero_group.update()
         self.hero_group.draw(self.surface)
       
         self.hero.bullet_group.update()
         self.hero.bullet_group.draw(self.surface)
       
     # 靜態方法,由於該方法內不須要傳入任何屬性或類對象    
     @ staticmethod
     def gameOver():
         print("遊戲結束...")
         pygame.quit()
         exit()
# 主程序的入口    

if __name__ == "__main__":

    pg = PlaneGame()

    pg.startGame()

總結

雖然這是一個不完整的飛機大戰,可是基本功能已經實現,對於剛入門的人(好比我)來講,作完仍是會有點小小成就感的。遊戲素材能夠自行去網上下載,裏面有些參數須要根據圖片的大小來進行設置。

歡迎添加微信(sy520518)跟我聯繫

本文分享自微信公衆號 - 佛系編程人(py520llj)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索