Pygame庫200行代碼實現簡易飛機大戰
寫在開頭,因為這個小遊戲的實驗主要是幫助我熟悉pygame庫的使用,所以遊戲的一些地方可能存在不完善處,還望包涵。
安裝使用庫
pygame簡介
pygame是跨平臺python模塊,專為電子遊戲設計,包括圖像、聲音。建立在SDL基礎上,允許實時電子遊戲研發而無需被低級語言束縛, 開發者可以把精力放在遊戲的架構上。
pgame中主要模塊介紹
(1) pygame
pygame模塊會自動導入其它的pygame相關模塊。
pygame模塊包括surface函數, 可以返回一個新的surface 對象。 init()函數是pygame遊戲的核心,必須在進入遊戲的主循環之前調用。init()會自動初始化其它所有模塊。
(2) pygame.locals
包括在你自己的模塊作用域內使用的名字(變量)。包括事件類型、鍵和視頻模式等的名字。
(3) pygame.display
包括處理pygame顯示方式的函數。包括普通窗口和全屏模式。 pygame.display中一些常用的方法如下:
- flip:更新顯示。
- update:更新一部分時候使用update。
- set_mode:設定顯示的類型和尺寸。
- set_caption:設定pygame程序的標題。
- get_surface:調用flip和blit前返回一個可用於畫圖的surface對象。
(4) pygame.font
包括font函數,用於表現不同的字體。
(5) pygame.sprite
遊戲精靈,Group用做sprite對象的容器。調用group對象的update對象,會自動調用所有sprite對象的update方法。
(6) pygame.mouse
隱藏鼠標光標,獲取鼠標位置。
(7) pygame.event
追蹤鼠標單擊、按鍵按下和釋放等事件。
(8) pygame.image
用於處理保存在GIF、PNG或者JPEG文件內的圖像。
註:程序中除瞭local模塊和font模塊沒有使用,其他模塊均有涉及。
pygame的安裝
你可以選擇使用pycharm中工具欄下方的python packages
搜索pygame進行安裝,當然也可以使用cmd命令符中常用的pip install pygame
的方法。
安裝超時網速慢,直接超時,可以指定國內源鏡像。
pip install -i 國內鏡像地址 包名
例如: pip install -i https://mirrors.aliyun.com/pypi/simple/ numpy
國內常用源鏡像地址:
清華:https://pypi.tuna.tsinghua.edu.cn/simple
阿裡雲:http://mirrors.aliyun.com/pypi/simple/
中國科技大學: https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣:http://pypi.douban.com/simple/
驗證安裝
驗證pygame是否安裝成功,在cmd命令符中使用 pip list
語句,如果安裝成功,我們可以在下方結果中找到。
程序原理
首先創建遊戲的主窗體,主窗體的大小就是你背景圖片的大小。
import pygame #遊戲初始化 pygame.init() #創建遊戲主窗口 screen = pygame.display.set_mode((480,700)) #繪制背景圖香 #1 加載圖像數據 background = pygame.image.load('./image/background.png') #2 blit繪制圖像 #從左上角繪制 screen.blit(background,(0,0)) pygame.display.update() #卸載所有的模塊 pygame.quit()
繪制圖像時的方向,後面我們主機、敵機、背景、子彈的方向都需要註意這一點。
背景圖像繪制完之後就是我們主機、敵機的繪制,我們可以在所有的繪制工作完成後再統一調用update方法
#繪制飛機圖片 hero = pygame.image.load('./image/hero2.png') screen.blit(hero,(150,300)) pygame.display.update()
其實飛機大戰的原理和動畫片的原理一致,我們需要對一個個按下的指令進行反應,從而形成一個連貫的畫面,這裡我們就需要使用到pygame庫中的time模塊
#創造時鐘對象 屏幕繪制速率 clock = pygame.time.Clock() #遊戲循環 while True: #指定循環體內部代碼的執行頻率 每秒重復60次 clock.tick(60) #將移動前飛機進行遮擋 達到動畫效果 screen.blit(background, (0, 0)) screen.blit(hero,hero_rect)
如果你想停止程序,發現點擊窗體右上角的關閉並無反應,因為你還未在循環體內進行事件監聽,然後對時間進行判斷
event_list = pygame.event.get() for event in event_list: #判斷是否為退出事件 if event.type == pygame.QUIT: print("退出遊戲...") #卸載所有模塊 pygame.quit() exit()
關於敵機的生成我們需要使用到sprite精靈和精靈組模塊,創建兩個一樣的敵機,但是敵機的飛行速度不一樣,然後將敵機精靈添加至敵機精靈組中,然後在循環體中我們不斷將敵機精靈組進行繪制即可
enemy = GameSprite("./image/enemy0.png") enemy1 = GameSprite("./image/enemy0.png",2) enemy_group = pygame.sprite.Group(enemy,enemy1) #精靈組調用方法 enemy_group.update() enemy_group.draw(screen)
對上述部分代碼進行整理簡化,最後我們可以得到這樣的效果圖,主機和敵機都可以移動
import pygame from plane_sprites import * #遊戲初始化 pygame.init() #創建遊戲主窗口 screen = pygame.display.set_mode((480,700)) #繪制背景圖香 #1 加載圖像數據 background = pygame.image.load('./image/background.png') #2 blit繪制圖像 #從左上角繪制 screen.blit(background,(0,0)) #3 update更新屏幕顯示 # pygame.display.update() #繪制飛機圖片 hero = pygame.image.load('./image/hero2.png') screen.blit(hero,(150,300)) #可以在所有繪制工作完成後,統一調用update方法 pygame.display.update() #創造時鐘對象 屏幕繪制速率 clock = pygame.time.Clock() #定義飛機初始位置 hero_rect = pygame.Rect(150,300,100,122) #敵機精靈創建 enemy = GameSprite("./image/enemy0.png") enemy1 = GameSprite("./image/enemy0.png",2) enemy_group = pygame.sprite.Group(enemy,enemy1) #遊戲循環 while True: #指定循環體內部代碼的執行頻率 每秒重復60次 clock.tick(60) #監聽時間 event_list = pygame.event.get() # if len(event_list)>0: # print(event_list) for event in event_list: #判斷是否為退出事件 if event.type == pygame.QUIT: print("退出遊戲...") #卸載所有模塊 pygame.quit() exit() hero_rect.y -= 1 if hero_rect.y <=0: hero_rect.y = 700 #將移動前飛機進行遮擋 達到動畫效果 screen.blit(background, (0, 0)) screen.blit(hero,hero_rect) #精靈組調用方法 enemy_group.update() enemy_group.draw(screen) pygame.display.update() pass pygame.quit()
程序升級
設置飛機大戰的精靈類和常量
這裡的update方法主要是在為瞭後面背景類、敵機類和子彈類中達到可以垂直飛行的效果
#屏幕大小 SCREEN_RECT = pygame.Rect(0,0,480,700) #刷新幀率 SCREEN_PER_SEC = 60 #創建敵機的定時器常量 CREATE_ENEMY_EVENT = pygame.USEREVENT #英雄發射子彈事件 HERO_FIRE_EVENT = pygame.USEREVENT + 1 class GameSprite(pygame.sprite.Sprite): def __init__(self,image_name,speed=1): #調用父類初始化方法 super().__init__() #定義對象屬性 self.image = pygame.image.load(image_name) self.rect = self.image.get_rect() self.speed = speed #更新顯示 def update(self): self.rect.y += self.speed
背景類和敵機類
因為想要背景會隨著移動,所以在背景類中的init設置瞭is_alt參數,用來添加背景到原圖像的上方,這樣就可以達到背景滾動的效果。
在敵機類中對敵機的位置進行判斷,如果敵機超過我們預設屏幕y的方位就會使用kill()方法從精靈組中刪除,敵機生成的位置和速度采用瞭random隨機數的randint()方法
class Background(GameSprite): #遊戲背景滾動 def __init__(self,is_alt=False): #調用父類中精靈中的創建 image/rect/speed super().__init__("./image/background.png") if is_alt: self.rect.y = -self.rect.height def update(self): super().update() #如果移出屏幕,將圖像移到屏幕上訪 if self.rect.y >= SCREEN_RECT.height: self.rect.y = -self.rect.height class Enemy(GameSprite): #敵機精靈 def __init__(self): #1 調用父類方法 創建敵機精靈 super().__init__("./image/enemy0.png") #2 指定敵機初始隨機速度 self.speed = random.randint(1,2) #3 指定敵機初始隨機位置 self.rect.bottom = 0 max_x = SCREEN_RECT.width - self.rect.width self.rect.x = random.randint(0,max_x) def update(self): #!調用父類方法 垂直方向飛行 super().update() #2 判斷是否飛出屏幕 如果是,需要從精靈組中刪除 if self.rect.y >= SCREEN_RECT.height: print("飛出屏幕,需要從精靈組中刪除...") #kill方法可以將精靈從精靈族中移出,精靈自動銷毀 self.kill() def __del__(self): print("敵機死亡 %s" % self.rect)
主機類和子彈類
SCREEN_RECT.centerx是用來保證一開始主機初始在屏幕中央部分,關於主機的y因為在一開始畫瞭一張繪制示意圖所以這裡應該為屏幕的SCREEN_RECT.bottom減去部分距離。
子彈類中和敵機類同理需要判斷是否飛出屏幕范圍,如果超過使用kill()方法從精靈組中刪除,子彈的初始位置應該是主機的上方,既子彈的x等於主機的x
#主角飛機 class Hero(GameSprite): def __init__(self): # 調用父類 設置英雄圖像和速度 super().__init__("./image/hero2.png",0) # 設置主機位置 self.rect.centerx = SCREEN_RECT.centerx self.rect.bottom = SCREEN_RECT.bottom - 50 # 子彈精靈組 self.bullet_group = pygame.sprite.Group() def update(self): #水平方向移動 self.rect.x += self.speed #控制英雄不能為0 if self.rect.x < 0: self.rect.x =0 elif self.rect.right > SCREEN_RECT.right: self.rect.right = SCREEN_RECT.right #子彈發射 def fire(self): print("發射子彈...") #創建子彈精靈 bullet = Bullet() #設置子彈位置 bullet.rect.bottom = self.rect.y-20 bullet.rect.centerx = self.rect.centerx #添加到子彈精靈組中 self.bullet_group.add(bullet) #子彈類 class Bullet(GameSprite): def __init__(self): #調用父類方法 設置子彈圖片速度 super().__init__("./image/bullet1.png",-2) def update(self): #調用父類方法 讓子彈垂直飛行 super().update() #判斷子彈是否飛出 if self.rect.bottom < 0: self.kill() def __del__(self): print("子彈被銷毀")
主遊戲類
在主類中進行精靈組的創建,背景精靈組的創建是為瞭達到背景滾動的效果
#精靈組的創建 def __create_sprites(self): #創建背景精靈和精靈1組 bg1 = Background() bg2 = Background(True) self.back_group = pygame.sprite.Group(bg1,bg2) #創建敵機精靈和精靈組 self.enemy_group = pygame.sprite.Group( #創建英雄精靈和精靈組 self.hero = Hero() self.hero_group = pygame.sprite.Group(self.hero)
遊戲的初始化
def __init__(self): print("遊戲初始化") #創建遊戲窗口 self.screen = pygame.display.set_mode(SCREEN_RECT.size) #創建遊戲時鐘 self.clock = pygame.time.Clock() self.__create_sprites() #敵機生成和主機開火的定時器 pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)#單位是ms pygame.time.set_timer(HERO_FIRE_EVENT,500)
事件監聽方法
關於事件的監聽過程中,需要對敵機生成和子彈飛行、主機移動指令做出對應反應
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("敵機生成...") #創建敵機精靈 enemy = Enemy() #敵機精靈加入精靈組 self.enemy_group.add(enemy) elif event.type == HERO_FIRE_EVENT: print("發射子彈...") self.hero.fire() #飛機移動 keyss_pressed = pygame.key.get_pressed() if keyss_pressed[pygame.K_RIGHT]: print("向右移動") self.hero.speed = 2 elif keyss_pressed[pygame.K_LEFT]: print("向左移動") self.hero.speed = -2 else: self.hero.speed = 0
碰撞檢測
對於子彈碰撞敵機和敵機碰撞主機的情況進行判定
#碰撞檢測 def __check_collide(self): #子彈摧毀敵機 pygame.sprite.groupcollide(self.hero.bullet_group,self.enemy_group,True,True) #敵機撞毀英雄 enemies = pygame.sprite.spritecollide(self.hero, self.enemy_group, True) if len(enemies) > 0: self.hero.kill() PlaneGame.__game_over()
精靈組更新顯示
#精靈更新顯示 def __update_sprites(self): #背景精靈組 self.back_group.update() self.back_group.draw(self.screen) #敵機精靈組 self.enemy_group.update() self.enemy_group.draw(self.screen) #主機精靈組 self.hero_group.update() self.hero_group.draw(self.screen) #子彈精靈組 self.hero.bullet_group.update() self.hero.bullet_group.draw(self.screen)
遊戲的開始與結束
def start_game(self): print("遊戲開始...") while True: #1 設置刷新幀率 self.clock.tick(SCREEN_PER_SEC) #2 時間監聽 self.__event_handler() #3 碰撞檢測 self.__check_collide() #4 更新敵機 self.__update_sprites() #5 更新顯示 pygame.display.update() @staticmethod def __game_over(): print("遊戲結束") pygame.quit() exit()
程序總結
程序中print語句是為瞭我在運行中進行功能的檢測,可以直接註釋掉,對於整個程序的運行並無影響。遊戲隻是簡單的規則,主機可以左右移動,敵機會隨機從上方垂直下來,敵機撞到主機之後就會遊戲結束直接關閉遊戲窗體,比如擊毀敵機也沒有得分這一設置,這些都是可以再對規則進行優化的部分,因為隻是為瞭幫助我熟悉pygame庫的功能,所以代碼並未寫的更加詳細,感興趣的話你可以對代碼部分進行更改達到你想要的效果,程序升級部分並未進行太多的文字解釋部分,在代碼中我保留瞭我的註釋部分方便你對代碼進行解讀。
程序中用到的素材以及未使用到的音樂都在鏈接中。
到此這篇關於Pygame庫200行代碼實現簡易飛機大戰 的文章就介紹到這瞭,更多相關Pygame 飛機大戰 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- python第三方庫pygame的使用詳解
- Python+Pygame實戰之實現小蜜蜂歷險記遊戲
- 如何利用pygame實現打飛機小遊戲
- Python遊戲開發之精靈和精靈組
- Python pygame項目實戰英雄動畫特效實現