pygame 模塊進(jìn)行簡(jiǎn)單游戲開發(fā)-----飛機(jī)大戰(zhàn)

學(xué)習(xí)目標(biāo)

  • 強(qiáng)化 面向?qū)ο?程序設(shè)計(jì)
  • 體驗(yàn)使用 pygame 模塊進(jìn)行 游戲開發(fā)
安裝 pygame
 sudo pip3 install pygame
驗(yàn)證安裝
python3 -m pygame.examples.aliens
1.1硼讽、 游戲的初始化和退出
import pygame
pygame.init()
# 游戲代碼... 
pygame.quit()
1.2乏德、 理解游戲中的坐標(biāo)系
  • 定義 hero_rect 矩形描述 英雄的位置和大小
  • 輸出英雄的 坐標(biāo)原點(diǎn)(x 和 y)
  • 輸出英雄的 尺寸(寬度 和 高度)
hero_rect = pygame.Rect(100, 500, 120, 126)
print("坐標(biāo)原點(diǎn) %d %d" % (hero_rect.x, hero_rect.y))
print("英雄大小 %d %d" % (hero_rect.width, hero_rect.height))  
# size 屬性會(huì)返回矩形區(qū)域的 (寬, 高) 元組
print("英雄大小 %d %d" % hero_rect.size)
1.3寿酌、 創(chuàng)建游戲主窗口
# 創(chuàng)建游戲主窗口
screen = pygame.display.set_mode((480, 700))
1.4、 簡(jiǎn)單的游戲循環(huán)
# 創(chuàng)建游戲主窗口
screen = pygame.display.set_mode((480, 700))

# 游戲循環(huán)
while True:
    pass

2啃沪、 理解 圖像 并實(shí)現(xiàn)圖像繪制

2.1枪孩、繪制背景圖像
# 繪制背景圖像
# 1> 加載圖像
bg = pygame.image.load("./images/background.png")
# 2> 繪制在屏幕
screen.blit(bg, (0, 0))
# 3> 更新顯示
pygame.display.update()
2.2、繪制英雄圖像
# 1> 加載圖像
hero = pygame.image.load("./images/me1.png")
# 2> 繪制在屏幕
screen.blit(hero, (200, 500))
# 3> 更新顯示
pygame.display.update()

可以在 screen 對(duì)象完成 所有 blit 方法之后甚侣,統(tǒng)一調(diào)用一次 display.update 方法明吩,同樣可以在屏幕上 看到最終的繪制結(jié)果

案例調(diào)整
# 繪制背景圖像
# 1> 加載圖像
bg = pygame.image.load("./images/background.png")
# 2> 繪制在屏幕
screen.blit(bg, (0, 0))
# 繪制英雄圖像
# 1> 加載圖像
hero = pygame.image.load("./images/me1.png")
# 2> 繪制在屏幕
screen.blit(hero, (200, 500))
# 3> 更新顯示 - update 方法會(huì)把之前所有繪制的結(jié)果,一次性更新到屏幕窗口上
pygame.display.update()

3. 創(chuàng)建游戲時(shí)鐘對(duì)象

3.1殷费、游戲時(shí)鐘
clock = pygame.time.Clock()
i = 0
# 游戲循環(huán)
while True:
    # 設(shè)置屏幕刷新幀率
    clock.tick(60)
    print(i)
    i += 1
3.2印荔、 英雄的簡(jiǎn)單動(dòng)畫實(shí)現(xiàn)
    # 4. 定義英雄的初始位置
    hero_rect = pygame.Rect(150, 500, 102, 126)
    while True:
            # 可以指定循環(huán)體內(nèi)部的代碼執(zhí)行的頻率
            clock.tick(60)
            # 更新英雄位置
            hero_rect.y -= 1
            # 如果移出屏幕,則將英雄的頂部移動(dòng)到屏幕底部
            if hero_rect.y <= 0:
                    hero_rect.y = 700
            # 繪制背景圖片
            screen.blit(bg, (0, 0))
            # 繪制英雄圖像
            screen.blit(hero, hero_rect)
            # 更新顯示
            pygame.display.update()
注意:
  1. 英雄向上飛行详羡,當(dāng) 英雄完全從上方飛出屏幕后
  2. 將飛機(jī)移動(dòng)到屏幕的底部
if hero_rect.bottom <= 0:
    hero_rect.y = 700
3.3仍律、 在游戲循環(huán)中 監(jiān)聽 事件
    # 游戲循環(huán)
    while True:
          # 設(shè)置屏幕刷新幀率
          clock.tick(60)
          #  事件監(jiān)聽
          for event in pygame.event.get():
                # 判斷用戶是否點(diǎn)擊了關(guān)閉按鈕
                if event.type == pygame.QUIT:
                      print("退出游戲...")
                      pygame.quit()
                      # 直接退出系統(tǒng)
                      exit()
4.1、 精靈 和 精靈組
import pygame
class GameSprite(pygame.sprite.Sprite):
 """游戲精靈基類"""
    def __init__(self, image_name, speed=1):
    # 調(diào)用父類的初始化方法
        super().__init__()
        # 加載圖像
        self.image = pygame.image.load(image_name)
        # 設(shè)置尺寸
        self.rect = self.image.get_rect()
       # 記錄速度
        self.speed = speed
    def update(self, *args):
        # 默認(rèn)在垂直方向移動(dòng)
        self.rect.y += self.speed
4.2实柠、 使用 游戲精靈 和 精靈組 創(chuàng)建敵機(jī)
  1. 導(dǎo)入 plane_sprites 模塊

     from plane_sprites import *
    
  2. 修改初始化部分代碼

# 創(chuàng)建敵機(jī)精靈和精靈組
enemy1 = GameSprite("./images/enemy1.png")
enemy2 = GameSprite("./images/enemy1.png", 2)
enemy2.rect.x = 200
enemy_group = pygame.sprite.Group(enemy1, enemy2)
  1. 修改游戲循環(huán)部分代碼
# 讓敵機(jī)組調(diào)用 update 和 draw 方法
enemy_group.update()
enemy_group.draw(screen)
# 更新屏幕顯示
pygame.display.update()
5.1水泉、實(shí)現(xiàn)飛機(jī)大戰(zhàn)主游戲類
import pygame
from plane_sprites import *
class PlaneGame(object):
"""飛機(jī)大戰(zhàn)主游戲"""
    def __init__(self):
        print("游戲初始化")
    def start_game(self):
        print("開始游戲...")
if __name__ == '__main__':
    # 創(chuàng)建游戲?qū)ο?    game = PlaneGame()
    # 開始游戲
    game.start_game()
5.2、 游戲初始化部分
  • 完成 init() 代碼如下:

      def __init__(self):
          print("游戲初始化")
          # 1. 創(chuàng)建游戲的窗口
          self.screen = pygame.display.set_mode((480, 700))
          # 2. 創(chuàng)建游戲的時(shí)鐘
          self.clock = pygame.time.Clock()
          # 3. 調(diào)用私有方法窒盐,精靈和精靈組的創(chuàng)建
          self.__create_sprites()
      def __create_sprites(self):
          pass
    
5.3草则、使用 常量 代替固定的數(shù)值
  • 在 plane_sprites.py 中增加常量定義

      import pygame
      # 游戲屏幕大小
      SCREEN_RECT = pygame.Rect(0, 0, 480, 700)
    
  • 修改 plane_main.py 中的窗口大小

     self.screen = pygame.display.set_mode(SCREEN_RECT.size)
    
5.4、 游戲循環(huán)部分
  • 完成 start_game() 基礎(chǔ)代碼如下:

      def start_game(self):
      """開始游戲"""
          print("開始游戲...")
          while True:
              # 1. 設(shè)置刷新幀率
              self.clock.tick(60)
              # 2. 事件監(jiān)聽
              self.__event_handler()
              # 3. 碰撞檢測(cè)
              self.__check_collide()
              # 4. 更新精靈組
              self.__update_sprites()
              # 5. 更新屏幕顯示
              pygame.display.update()
      def __event_handler(self):
      """事件監(jiān)聽"""
          for event in pygame.event.get():
              if event.type == pygame.QUIT:
                  PlaneGame.__game_over()
      def __check_collide(self):
      """碰撞檢測(cè)"""
          pass
      def __update_sprites(self):
        """更新精靈組"""
          pass
    
      @staticmethod
      def __game_over(): 
      """游戲結(jié)束"""
    
           print("游戲結(jié)束")
           pygame.quit()
           exit()
    
5.5蟹漓、準(zhǔn)備游戲精靈組
  • 創(chuàng)建精靈組方法

      def __create_sprites(self):
       """創(chuàng)建精靈組"""
          # 背景組
          self.back_group = pygame.sprite.Group()
          # 敵機(jī)組
          self.enemy_group = pygame.sprite.Group()
          # 英雄組
          self.hero_group = pygame.sprite.Group()
    
  • 更新精靈組方法

     def __update_sprites(self):
     """更新精靈組"""
          for group in [self.back_group, self.enemy_group, self.hero_group]:
              group.update()
              group.draw(self.screen)
    
6.1炕横、 背景精靈的基本實(shí)現(xiàn)
  • 在 plane_sprites 新建 Background 繼承自 GameSprite

       class Background(GameSprite):
       """游戲背景精靈"""
          def update(self):
          # 1. 調(diào)用父類的方法實(shí)現(xiàn)
              super().update()
              # 2. 判斷是否移出屏幕,如果移出屏幕葡粒,將圖像設(shè)置到屏幕的上方
              if self.rect.y >= SCREEN_RECT.height:
                  self.rect.y = -self.rect.height
    
6.2份殿、 在 plane_main.py 中顯示背景精靈

__create_sprites 方法

def __create_sprites(self):
# 創(chuàng)建背景精靈和精靈組
    bg1 = Background("./images/background.png")
    bg2 = Background("./images/background.png")
    bg2.rect.y = -bg2.rect.height
    self.back_group = pygame.sprite.Group(bg1, bg2)

__update_sprites 方法

def __update_sprites(self):
    self.back_group.update()
    self.back_group.draw(self.screen)
6.3、 利用初始化方法嗽交,簡(jiǎn)化背景精靈創(chuàng)建

在 plane_sprites.py 中實(shí)現(xiàn) Background 的 初始化方法

def __init__(self, is_alt=False):
    image_name = "./images/background.png"
    super().__init__(image_name)
    # 判斷是否交替圖片伯铣,如果是,將圖片設(shè)置到屏幕頂部
    if is_alt:
        self.rect.y = -self.rect.height
  • 修改 plane_main 的 __create_sprites 方法

    # 創(chuàng)建背景精靈和精靈組
    bg1 = Background()
    bg2 = Background(True)
    self.back_group = pygame.sprite.Group(bg1, bg2)
    
7.1轮纫、敵機(jī)出場(chǎng)
  1. 定義事件
  • 在 plane_sprites.py 的頂部定義 事件常量

    # 敵機(jī)的定時(shí)器事件常量
    CREATE_ENEMY_EVENT = pygame.USEREVENT
    
  • 在 PlaneGame 的 初始化方法 中 創(chuàng)建用戶事件

    # 4. 設(shè)置定時(shí)器事件 - 每秒創(chuàng)建一架敵機(jī)
    pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
    
  1. 監(jiān)聽定時(shí)器事件
  • 在 __event_handler 方法中增加以下代碼:

    def __event_handler(self):
       for event in pygame.event.get():
           # 判斷是否退出游戲
           if event.type == pygame.QUIT:
               PlaneGame.__game_over()
               elif event.type == CREATE_ENEMY_EVENT:
               print("敵機(jī)出場(chǎng)...")
    
7.2腔寡、設(shè)計(jì) Enemy 類
class Enemy(GameSprite):
"""敵機(jī)精靈"""
    def __init__(self):
        # 1. 調(diào)用父類方法,創(chuàng)建敵機(jī)精靈掌唾,并且指定敵機(jī)的圖像
        super().__init__("./images/enemy1.png")
        # 2. 設(shè)置敵機(jī)的隨機(jī)初始速度
        # 3. 設(shè)置敵機(jī)的隨機(jī)初始位置
    def update(self):
        # 1. 調(diào)用父類方法放前,讓敵機(jī)在垂直方向運(yùn)動(dòng)
        super().update()
        # 2. 判斷是否飛出屏幕,如果是糯彬,需要將敵機(jī)從精靈組刪除
        if self.rect.y >= SCREEN_RECT.height:
            print("敵機(jī)飛出屏幕...")
7.3凭语、創(chuàng)建敵機(jī)
  • 修改 plane_main 的 __create_sprites 方法

    # 敵機(jī)組
    self.enemy_group = pygame.sprite.Group()
    
  • 修改 plane_main 的 __update_sprites 方法

    self.enemy_group.update()
    self.enemy_group.draw(self.screen)
    
  • 定時(shí)出現(xiàn)敵機(jī)

    elif event.type == CREATE_ENEMY_EVENT:
    self.enemy_group.add(Enemy())
    
  • 修改 plane_sprites.py 增加 random 的導(dǎo)入

     import random
    
7.4、隨機(jī)速度
  def __init__(self):
      # 1. 調(diào)用父類方法撩扒,創(chuàng)建敵機(jī)精靈似扔,并且指定敵機(jī)的圖像
      super().__init__("./images/enemy1.png")
      # 2. 設(shè)置敵機(jī)的隨機(jī)初始速度 1 ~ 3
      self.speed = random.randint(1, 3)
      # 3. 設(shè)置敵機(jī)的隨機(jī)初始位置
      self.rect.bottom = 0
      max_x = SCREEN_RECT.width - self.rect.width
      self.rect.x = random.randint(0, max_x)
7.5吨些、移出屏幕銷毀敵機(jī)
def update(self):
    super().update()
    # 判斷敵機(jī)是否移出屏幕
    if self.rect.y >= SCREEN_RECT.height:
        # 將精靈從所有組中刪除
        self.kill()
8.1、準(zhǔn)備英雄類
class Hero(GameSprite):
"""英雄精靈"""
    def __init__(self):
        super().__init__("./images/me1.png", 0)
        # 設(shè)置初始位置
        self.rect.centerx = SCREEN_RECT.centerx
        self.rect.bottom = SCREEN_RECT.bottom - 120
8.2炒辉、 繪制英雄
  • 修改 __create_sprites 方法如下:

    # 英雄組
    self.hero = Hero()
    self.hero_group = pygame.sprite.Group(self.hero)
    
  • 修改 __update_sprites 方法如下:

    self.hero_group.update()
    self.hero_group.draw(self.screen)
    
8.3豪墅、移動(dòng)英雄位置
 # 返回所有按鍵的元組,如果某個(gè)鍵被按下黔寇,對(duì)應(yīng)的值會(huì)是1
 keys_pressed = pygame.key.get_pressed()
 # 判斷是否按下了方向鍵
 if keys_pressed[pygame.K_RIGHT]:
     print("向右移動(dòng)...")
  • 在 Hero 類偶器,重寫 update() 方法,根據(jù)速度水平移動(dòng) 英雄的飛機(jī)

    def update(self):
    # 飛機(jī)水平移動(dòng)
    self.rect.x += self.speed
    
  • 調(diào)整鍵盤按鍵代碼

    # 獲取用戶按鍵
    keys_pressed = pygame.key.get_pressed()
    if keys_pressed[pygame.K_RIGHT]:
        self.hero.speed = 2
    elif keys_pressed[pygame.K_LEFT]:
        self.hero.speed = -2
    else:
        self.hero.speed = 0
    
8.4缝裤、控制英雄運(yùn)動(dòng)邊界
 def update(self):
     # 飛機(jī)水平移動(dòng)
     self.rect.x += self.speed
     # 判斷屏幕邊界
     if self.rect.left < 0:
         self.rect.left = 0
     if self.rect.right > SCREEN_RECT.right:
         self.rect.right = SCREEN_RECT.right
9.1屏轰、發(fā)射子彈
  • 在 Hero 中定義 fire 方法

    def fire(self):
    print("發(fā)射子彈...")
    
  • 在 plane_main.py 的頂部定義 發(fā)射子彈 事件常量

    # 英雄發(fā)射子彈事件
    HERO_FIRE_EVENT = pygame.USEREVENT + 1
    
  • init 方法末尾中添加 發(fā)射子彈 事件

    # 每隔 0.5 秒發(fā)射一次子彈
    pygame.time.set_timer(HERO_FIRE_EVENT, 500)
    
  • 在 __event_handler 方法中讓英雄發(fā)射子彈

    elif event.type == HERO_FIRE_EVENT:
        self.hero.fire()
    
9.2、定義子彈類
class Bullet(GameSprite):
   """子彈精靈"""
    def __init__(self):
        super().__init__("./images/bullet1.png", -2)
    def update(self):
        super().update()
        # 判斷是否超出屏幕憋飞,如果是霎苗,從精靈組刪除
        if self.rect.bottom < 0:
            self.kill()
9.3、發(fā)射子彈
  • 初始化方法

    # 創(chuàng)建子彈的精靈組
    self.bullets = pygame.sprite.Group()
    
  • 修改 fire() 方法

    def fire(self):
        # 1. 創(chuàng)建子彈精靈
        bullet = Bullet()
        # 2. 設(shè)置精靈的位置
        bullet.rect.bottom = self.rect.y - 20
        bullet.rect.centerx = self.rect.centerx
        # 3. 將精靈添加到精靈組
        self.bullets.add(bullet)
    

10榛做、碰撞實(shí)現(xiàn)

  def __check_collide(self):
      # 1. 子彈摧毀敵機(jī)
      pygame.sprite.groupcollide(self.hero.bullets, self.enemy_group, True, True)
      # 2. 敵機(jī)撞毀英雄
      enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True)
      # 判斷列表時(shí)候有內(nèi)容
      if len(enemies) > 0:
          # 讓英雄犧牲
         self.hero.kill()
         # 結(jié)束游戲
         PlaneGame.__game_over()

游戲界面效果:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叨粘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瘤睹,更是在濱河造成了極大的恐慌升敲,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轰传,死亡現(xiàn)場(chǎng)離奇詭異驴党,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)获茬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門港庄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人恕曲,你說我怎么就攤上這事鹏氧。” “怎么了佩谣?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵把还,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我茸俭,道長(zhǎng)吊履,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任调鬓,我火速辦了婚禮艇炎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腾窝。我一直安慰自己缀踪,他們只是感情好居砖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驴娃,像睡著了一般奏候。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上托慨,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天鼻由,我揣著相機(jī)與錄音暇榴,去河邊找鬼厚棵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蔼紧,可吹牛的內(nèi)容都是我干的婆硬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼奸例,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼彬犯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起查吊,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤谐区,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逻卖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宋列,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年评也,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炼杖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盗迟,死狀恐怖坤邪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情罚缕,我是刑警寧澤艇纺,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站邮弹,受9級(jí)特大地震影響喂饥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肠鲫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一员帮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧导饲,春花似錦捞高、人聲如沸氯材。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氢哮。三九已至,卻和暖如春型檀,著一層夾襖步出監(jiān)牢的瞬間冗尤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工胀溺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裂七,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓仓坞,卻偏偏與公主長(zhǎng)得像背零,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子无埃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容