您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Pygame庫(kù)200行代碼實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)的示例分析,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
寫(xiě)在開(kāi)頭,因?yàn)檫@個(gè)小游戲的實(shí)驗(yàn)主要是幫助我熟悉pygame庫(kù)的使用,所以游戲的一些地方可能存在不完善處,還望包涵。
pygame是跨平臺(tái)python模塊,專(zhuān)為電子游戲設(shè)計(jì),包括圖像、聲音。建立在SDL基礎(chǔ)上,允許實(shí)時(shí)電子游戲研發(fā)而無(wú)需被低級(jí)語(yǔ)言束縛, 開(kāi)發(fā)者可以把精力放在游戲的架構(gòu)上。
(1) pygame
pygame模塊會(huì)自動(dòng)導(dǎo)入其它的pygame相關(guān)模塊。
pygame模塊包括surface函數(shù), 可以返回一個(gè)新的surface 對(duì)象。 init()函數(shù)是pygame游戲的核心,必須在進(jìn)入游戲的主循環(huán)之前調(diào)用。init()會(huì)自動(dòng)初始化其它所有模塊。
(2) pygame.locals
包括在你自己的模塊作用域內(nèi)使用的名字(變量)。包括事件類(lèi)型、鍵和視頻模式等的名字。
(3) pygame.display
包括處理pygame顯示方式的函數(shù)。包括普通窗口和全屏模式。 pygame.display中一些常用的方法如下:
flip:更新顯示。
update:更新一部分時(shí)候使用update。
set_mode:設(shè)定顯示的類(lèi)型和尺寸。
set_caption:設(shè)定pygame程序的標(biāo)題。
get_surface:調(diào)用flip和blit前返回一個(gè)可用于畫(huà)圖的surface對(duì)象。
(4) pygame.font
包括font函數(shù),用于表現(xiàn)不同的字體。
(5) pygame.sprite
游戲精靈,Group用做sprite對(duì)象的容器。調(diào)用group對(duì)象的update對(duì)象,會(huì)自動(dòng)調(diào)用所有sprite對(duì)象的update方法。
(6) pygame.mouse
隱藏鼠標(biāo)光標(biāo),獲取鼠標(biāo)位置。
(7) pygame.event
追蹤鼠標(biāo)單擊、按鍵按下和釋放等事件。
(8) pygame.image
用于處理保存在GIF、PNG或者JPEG文件內(nèi)的圖像。
注:程序中除了local模塊和font模塊沒(méi)有使用,其他模塊均有涉及。
你可以選擇使用pycharm中工具欄下方的python packages
搜索pygame進(jìn)行安裝,當(dāng)然也可以使用cmd命令符中常用的pip install pygame
的方法。
安裝超時(shí)網(wǎng)速慢,直接超時(shí),可以指定國(guó)內(nèi)源鏡像。
pip install -i 國(guó)內(nèi)鏡像地址 包名
例如: pip install -i https://mirrors.aliyun.com/pypi/simple/ numpy
國(guó)內(nèi)常用源鏡像地址:
清華:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中國(guó)科技大學(xué): https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣:http://pypi.douban.com/simple/
驗(yàn)證pygame是否安裝成功,在cmd命令符中使用 pip list
語(yǔ)句,如果安裝成功,我們可以在下方結(jié)果中找到。
首先創(chuàng)建游戲的主窗體,主窗體的大小就是你背景圖片的大小。
import pygame #游戲初始化 pygame.init() #創(chuàng)建游戲主窗口 screen = pygame.display.set_mode((480,700)) #繪制背景圖香 #1 加載圖像數(shù)據(jù) background = pygame.image.load('./image/background.png') #2 blit繪制圖像 #從左上角繪制 screen.blit(background,(0,0)) pygame.display.update() #卸載所有的模塊 pygame.quit()
繪制圖像時(shí)的方向,后面我們主機(jī)、敵機(jī)、背景、子彈的方向都需要注意這一點(diǎn)。
背景圖像繪制完之后就是我們主機(jī)、敵機(jī)的繪制,我們可以在所有的繪制工作完成后再統(tǒng)一調(diào)用update方法
#繪制飛機(jī)圖片 hero = pygame.image.load('./image/hero2.png') screen.blit(hero,(150,300)) pygame.display.update()
其實(shí)飛機(jī)大戰(zhàn)的原理和動(dòng)畫(huà)片的原理一致,我們需要對(duì)一個(gè)個(gè)按下的指令進(jìn)行反應(yīng),從而形成一個(gè)連貫的畫(huà)面,這里我們就需要使用到pygame庫(kù)中的time模塊
#創(chuàng)造時(shí)鐘對(duì)象 屏幕繪制速率 clock = pygame.time.Clock() #游戲循環(huán) while True: #指定循環(huán)體內(nèi)部代碼的執(zhí)行頻率 每秒重復(fù)60次 clock.tick(60) #將移動(dòng)前飛機(jī)進(jìn)行遮擋 達(dá)到動(dòng)畫(huà)效果 screen.blit(background, (0, 0)) screen.blit(hero,hero_rect)
如果你想停止程序,發(fā)現(xiàn)點(diǎn)擊窗體右上角的關(guān)閉并無(wú)反應(yīng),因?yàn)槟氵€未在循環(huán)體內(nèi)進(jìn)行事件監(jiān)聽(tīng),然后對(duì)時(shí)間進(jìn)行判斷
event_list = pygame.event.get() for event in event_list: #判斷是否為退出事件 if event.type == pygame.QUIT: print("退出游戲...") #卸載所有模塊 pygame.quit() exit()
關(guān)于敵機(jī)的生成我們需要使用到sprite精靈和精靈組模塊,創(chuàng)建兩個(gè)一樣的敵機(jī),但是敵機(jī)的飛行速度不一樣,然后將敵機(jī)精靈添加至敵機(jī)精靈組中,然后在循環(huán)體中我們不斷將敵機(jī)精靈組進(jìn)行繪制即可
enemy = GameSprite("./image/enemy0.png") enemy1 = GameSprite("./image/enemy0.png",2) enemy_group = pygame.sprite.Group(enemy,enemy1) #精靈組調(diào)用方法 enemy_group.update() enemy_group.draw(screen)
對(duì)上述部分代碼進(jìn)行整理簡(jiǎn)化,最后我們可以得到這樣的效果圖,主機(jī)和敵機(jī)都可以移動(dòng)
import pygame from plane_sprites import * #游戲初始化 pygame.init() #創(chuàng)建游戲主窗口 screen = pygame.display.set_mode((480,700)) #繪制背景圖香 #1 加載圖像數(shù)據(jù) background = pygame.image.load('./image/background.png') #2 blit繪制圖像 #從左上角繪制 screen.blit(background,(0,0)) #3 update更新屏幕顯示 # pygame.display.update() #繪制飛機(jī)圖片 hero = pygame.image.load('./image/hero2.png') screen.blit(hero,(150,300)) #可以在所有繪制工作完成后,統(tǒng)一調(diào)用update方法 pygame.display.update() #創(chuàng)造時(shí)鐘對(duì)象 屏幕繪制速率 clock = pygame.time.Clock() #定義飛機(jī)初始位置 hero_rect = pygame.Rect(150,300,100,122) #敵機(jī)精靈創(chuàng)建 enemy = GameSprite("./image/enemy0.png") enemy1 = GameSprite("./image/enemy0.png",2) enemy_group = pygame.sprite.Group(enemy,enemy1) #游戲循環(huán) while True: #指定循環(huán)體內(nèi)部代碼的執(zhí)行頻率 每秒重復(fù)60次 clock.tick(60) #監(jiān)聽(tīng)時(shí)間 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 #將移動(dòng)前飛機(jī)進(jìn)行遮擋 達(dá)到動(dòng)畫(huà)效果 screen.blit(background, (0, 0)) screen.blit(hero,hero_rect) #精靈組調(diào)用方法 enemy_group.update() enemy_group.draw(screen) pygame.display.update() pass pygame.quit()
這里的update方法主要是在為了后面背景類(lèi)、敵機(jī)類(lèi)和子彈類(lèi)中達(dá)到可以垂直飛行的效果
#屏幕大小 SCREEN_RECT = pygame.Rect(0,0,480,700) #刷新幀率 SCREEN_PER_SEC = 60 #創(chuàng)建敵機(jī)的定時(shí)器常量 CREATE_ENEMY_EVENT = pygame.USEREVENT #英雄發(fā)射子彈事件 HERO_FIRE_EVENT = pygame.USEREVENT + 1 class GameSprite(pygame.sprite.Sprite): def __init__(self,image_name,speed=1): #調(diào)用父類(lèi)初始化方法 super().__init__() #定義對(duì)象屬性 self.image = pygame.image.load(image_name) self.rect = self.image.get_rect() self.speed = speed #更新顯示 def update(self): self.rect.y += self.speed
因?yàn)橄胍尘皶?huì)隨著移動(dòng),所以在背景類(lèi)中的init設(shè)置了is_alt參數(shù),用來(lái)添加背景到原圖像的上方,這樣就可以達(dá)到背景滾動(dòng)的效果。
在敵機(jī)類(lèi)中對(duì)敵機(jī)的位置進(jìn)行判斷,如果敵機(jī)超過(guò)我們預(yù)設(shè)屏幕y的方位就會(huì)使用kill()方法從精靈組中刪除,敵機(jī)生成的位置和速度采用了random隨機(jī)數(shù)的randint()方法
class Background(GameSprite): #游戲背景滾動(dòng) def __init__(self,is_alt=False): #調(diào)用父類(lèi)中精靈中的創(chuàng)建 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): #敵機(jī)精靈 def __init__(self): #1 調(diào)用父類(lèi)方法 創(chuàng)建敵機(jī)精靈 super().__init__("./image/enemy0.png") #2 指定敵機(jī)初始隨機(jī)速度 self.speed = random.randint(1,2) #3 指定敵機(jī)初始隨機(jī)位置 self.rect.bottom = 0 max_x = SCREEN_RECT.width - self.rect.width self.rect.x = random.randint(0,max_x) def update(self): #!調(diào)用父類(lèi)方法 垂直方向飛行 super().update() #2 判斷是否飛出屏幕 如果是,需要從精靈組中刪除 if self.rect.y >= SCREEN_RECT.height: print("飛出屏幕,需要從精靈組中刪除...") #kill方法可以將精靈從精靈族中移出,精靈自動(dòng)銷(xiāo)毀 self.kill() def __del__(self): print("敵機(jī)死亡 %s" % self.rect)
SCREEN_RECT.centerx是用來(lái)保證一開(kāi)始主機(jī)初始在屏幕中央部分,關(guān)于主機(jī)的y因?yàn)樵谝婚_(kāi)始畫(huà)了一張繪制示意圖所以這里應(yīng)該為屏幕的SCREEN_RECT.bottom減去部分距離。
子彈類(lèi)中和敵機(jī)類(lèi)同理需要判斷是否飛出屏幕范圍,如果超過(guò)使用kill()方法從精靈組中刪除,子彈的初始位置應(yīng)該是主機(jī)的上方,既子彈的x等于主機(jī)的x
#主角飛機(jī) class Hero(GameSprite): def __init__(self): # 調(diào)用父類(lèi) 設(shè)置英雄圖像和速度 super().__init__("./image/hero2.png",0) # 設(shè)置主機(jī)位置 self.rect.centerx = SCREEN_RECT.centerx self.rect.bottom = SCREEN_RECT.bottom - 50 # 子彈精靈組 self.bullet_group = pygame.sprite.Group() def update(self): #水平方向移動(dòng) 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 #子彈發(fā)射 def fire(self): print("發(fā)射子彈...") #創(chuàng)建子彈精靈 bullet = Bullet() #設(shè)置子彈位置 bullet.rect.bottom = self.rect.y-20 bullet.rect.centerx = self.rect.centerx #添加到子彈精靈組中 self.bullet_group.add(bullet) #子彈類(lèi) class Bullet(GameSprite): def __init__(self): #調(diào)用父類(lèi)方法 設(shè)置子彈圖片速度 super().__init__("./image/bullet1.png",-2) def update(self): #調(diào)用父類(lèi)方法 讓子彈垂直飛行 super().update() #判斷子彈是否飛出 if self.rect.bottom < 0: self.kill() def __del__(self): print("子彈被銷(xiāo)毀")
在主類(lèi)中進(jìn)行精靈組的創(chuàng)建,背景精靈組的創(chuàng)建是為了達(dá)到背景滾動(dòng)的效果
#精靈組的創(chuàng)建 def __create_sprites(self): #創(chuàng)建背景精靈和精靈1組 bg1 = Background() bg2 = Background(True) self.back_group = pygame.sprite.Group(bg1,bg2) #創(chuàng)建敵機(jī)精靈和精靈組 self.enemy_group = pygame.sprite.Group( #創(chuàng)建英雄精靈和精靈組 self.hero = Hero() self.hero_group = pygame.sprite.Group(self.hero)
游戲的初始化
def __init__(self): print("游戲初始化") #創(chuàng)建游戲窗口 self.screen = pygame.display.set_mode(SCREEN_RECT.size) #創(chuàng)建游戲時(shí)鐘 self.clock = pygame.time.Clock() self.__create_sprites() #敵機(jī)生成和主機(jī)開(kāi)火的定時(shí)器 pygame.time.set_timer(CREATE_ENEMY_EVENT,1000)#單位是ms pygame.time.set_timer(HERO_FIRE_EVENT,500)
關(guān)于事件的監(jiān)聽(tīng)過(guò)程中,需要對(duì)敵機(jī)生成和子彈飛行、主機(jī)移動(dòng)指令做出對(duì)應(yīng)反應(yīng)
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ī)生成...") #創(chuàng)建敵機(jī)精靈 enemy = Enemy() #敵機(jī)精靈加入精靈組 self.enemy_group.add(enemy) elif event.type == HERO_FIRE_EVENT: print("發(fā)射子彈...") self.hero.fire() #飛機(jī)移動(dòng) keyss_pressed = pygame.key.get_pressed() if keyss_pressed[pygame.K_RIGHT]: print("向右移動(dòng)") self.hero.speed = 2 elif keyss_pressed[pygame.K_LEFT]: print("向左移動(dòng)") self.hero.speed = -2 else: self.hero.speed = 0
對(duì)于子彈碰撞敵機(jī)和敵機(jī)碰撞主機(jī)的情況進(jìn)行判定
#碰撞檢測(cè) def __check_collide(self): #子彈摧毀敵機(jī) pygame.sprite.groupcollide(self.hero.bullet_group,self.enemy_group,True,True) #敵機(jī)撞毀英雄 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) #敵機(jī)精靈組 self.enemy_group.update() self.enemy_group.draw(self.screen) #主機(jī)精靈組 self.hero_group.update() self.hero_group.draw(self.screen) #子彈精靈組 self.hero.bullet_group.update() self.hero.bullet_group.draw(self.screen)
游戲的開(kāi)始與結(jié)束
def start_game(self): print("游戲開(kāi)始...") while True: #1 設(shè)置刷新幀率 self.clock.tick(SCREEN_PER_SEC) #2 時(shí)間監(jiān)聽(tīng) self.__event_handler() #3 碰撞檢測(cè) self.__check_collide() #4 更新敵機(jī) self.__update_sprites() #5 更新顯示 pygame.display.update() @staticmethod def __game_over(): print("游戲結(jié)束") pygame.quit() exit()
關(guān)于Pygame庫(kù)200行代碼實(shí)現(xiàn)簡(jiǎn)易飛機(jī)大戰(zhàn)的示例分析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。