實戰項目:飛機大戰
項目目標:
實現基本的飛機大戰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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。