Python+Pygame實(shí)現(xiàn)懷舊游戲飛機(jī)大戰(zhàn)
前言
我第一次見到飛機(jī)大戰(zhàn)是在我小學(xué)五年級(jí)下半學(xué)期的時(shí)候(2020年),這個(gè)游戲中可以說(shuō)包含了幾乎所有我目前可接觸到的pygame知識(shí)。
一、python飛機(jī)大戰(zhàn)
下面用一個(gè)簡(jiǎn)單的飛機(jī)大戰(zhàn)游戲,串一下pygame基礎(chǔ)知識(shí)。
1.1 音樂
這里列舉一些常用函數(shù),詳細(xì)內(nèi)容請(qǐng)到pygame官網(wǎng)查看。
- pygame.mixer.music.load() :加載一個(gè)音樂文件用于播放;
- pygame.mixer.music.play() :播放音樂;
- pygame.mixer.music.rewind() :重新播放音樂;
- pygame.mixer.music.stop() : 結(jié)束音樂播放;
- pygame.mixer.music.pause() :暫停音樂播放;
- pygame.mixer.music.unpause() :恢復(fù)音樂播放;
- pygame.mixer.music.set_volume() :設(shè)置音量;
- pygame.mixer.music.get_volume() : 獲取音量。
1.2 精靈(spirte)
pygame場(chǎng)景里的動(dòng)態(tài)物體都可視為精靈,如主角,敵人,子彈,可移動(dòng)背景等等,換句話說(shuō),精靈就是一些動(dòng)態(tài)圖片,你要對(duì)這些圖片進(jìn)行一些交互操作,如移動(dòng),碰撞,爆炸等等。
Pygame提供了一個(gè)處理精靈的模塊,也就是sprite(pygame.sprite)模塊。我們使用該類Sprite來(lái)創(chuàng)建一個(gè)子類,真正達(dá)到處理精靈的目的,該子類提供了操作精靈的常用屬性和方法,如下所示:
- self.image:加載要顯示的精靈,控制圖片大小和填充顏色;
- self.rect:精靈圖片顯示在哪個(gè)位置;
- Sprite.update():刷新圖,相應(yīng)效果生效;
- Sprite.add():添加精靈圖到精靈組中(groups);
- Sprite.remove():從精靈組中刪除刪除的精靈圖;
- Sprite.kill():刪除精靈組中所有的精靈;
- Sprite.alive():判斷某個(gè)精靈是否屬于精靈組。
當(dāng)游戲中有大量的精靈時(shí),操作它們將變得復(fù)雜,此時(shí)通過構(gòu)建精靈容器(group 類)也就是精靈組來(lái)統(tǒng)一管理這些精靈。構(gòu)建方法如下:
# 創(chuàng)建精靈組 group = pygame.sprite.Group() # 向組內(nèi)添加一個(gè)精靈 group.add(sprite1)
1.3 事件(鍵盤事件,鼠標(biāo)事件)
鍵盤事件,這些會(huì)涉及到的日程安排操作,比如游戲批量的上下左右,或者人物中的前進(jìn)、后繼等操作,都需要鍵盤來(lái)配合執(zhí)行。
一個(gè)事件的關(guān)鍵點(diǎn),該事件可以進(jìn)行連續(xù)的連續(xù)性控制。一個(gè)關(guān)鍵點(diǎn)、組合屬性等以連續(xù)性的方式提供一系列事件,一系列常用的屬性將通過一系列的連續(xù)性的事件進(jìn)行排序。
- K_BACKSPACE:退格鍵(Backspace);
- K_TAB:制表鍵(Tab);
- K_CLEAR:清除鍵;
- K_RETURN:回車鍵(Enter);
- K_PAUSE:暫停鍵(Pause);
- K_ESCAPE:退出鍵(Escape);
- K_SPACE:空格鍵(空格);
- K_DELETE:刪除鍵(delete);
- K_UP向上:箭頭(向上箭頭);
- K_DOWN:箭頭(向下箭頭);
- K_RIGHT:向左(右箭頭);
- K_LEFT:向左箭頭(左箭頭)。
- KMOD_ALT:同時(shí)按下Alt鍵;
鼠標(biāo)事件,Pygame 提供了三個(gè)鼠標(biāo)事件:
pygame.event.MOUSEMOTION:鼠標(biāo)移動(dòng)事件;
pygame.event.MOUSEBUTTONUP:鼠標(biāo)鍵釋放事件;
pygame.event.MOUSEBUTTONDOWN:鼠標(biāo)鍵按下事件。
1.4 碰撞檢測(cè)
pygame.sprite.collide_rect():精靈之間的矩形檢測(cè),即兩個(gè)矩形區(qū)域是否有交匯,返回一個(gè)布爾值;
pygame.sprite.collide_circle():兩個(gè)精靈之間的圓形檢測(cè),即圓形區(qū)域是否有交匯,返回一個(gè)布爾值;
pygame.sprite.collide_mask():兩個(gè)精靈之間的像素蒙版檢測(cè),更為精準(zhǔn)的一種檢測(cè)方式;
pygame.sprite.spritecollide():精靈和精靈組之間的矩形碰撞檢測(cè),一個(gè)組內(nèi)的所有精靈會(huì)逐一地對(duì)另外一個(gè)單個(gè)精靈進(jìn)行碰撞檢測(cè),返回值是一個(gè)列表,包含了發(fā)生碰撞的所有精靈;
pygame.sprite.spritecollideany():精靈和精靈組之間的矩形碰撞檢測(cè),上述函數(shù)的變體,當(dāng)發(fā)生碰撞時(shí),返回組內(nèi)的一個(gè)精靈,無(wú)碰撞發(fā)生時(shí),返回 None;
pygame.sprite.groupcollide():檢測(cè)在兩個(gè)組之間發(fā)生碰撞的所有精靈,它返回值是一個(gè)字典,將第一組中發(fā)生碰撞的精靈作為鍵,第二個(gè)組中發(fā)生碰撞的精靈作為值。
1.5 更新
- pygame.display.update()
- pygame.display.flip()
flip函數(shù)將重新繪制整個(gè)屏幕對(duì)應(yīng)的窗口。update函數(shù)僅僅重新繪制窗口中有變化的區(qū)域。如果僅僅是幾個(gè)物體在移動(dòng),那么他只重繪其中移動(dòng)的部分,沒有變化的部分,并不進(jìn)行重繪。
update比f(wàn)lip速度更快。因此在一般的游戲中,如果不是場(chǎng)景變化非常頻繁的時(shí)候,建議使用update函數(shù),而不是flip函數(shù)。
1.6 總結(jié)及源碼
pygame可用函數(shù)有很多,但是真的不難,用文字講述很麻煩,所以我只是列舉了一些常用函數(shù)與方法,當(dāng)你用到的時(shí)候記得去官網(wǎng)或者百度搜搜就可以了,把完整代碼附在下面,僅供參考
# 導(dǎo)入兩個(gè)庫(kù) import pygame import random # 常量,屏幕寬高 WIDTH, HEIGHT = 800, 600 # 初始化操作 pygame.init() pygame.mixer.init() # 創(chuàng)建游戲窗口 screen = pygame.display.set_mode((WIDTH, HEIGHT)) # 設(shè)置游戲標(biāo)題 pygame.display.set_caption('飛機(jī)大戰(zhàn)') # 添加音樂 pygame.mixer.music.load('./sound/bgLoop.wav') pygame.mixer.music.set_volume(0.5) # 音量 pygame.mixer.music.play(-1, 0) # 添加系統(tǒng)時(shí)鐘,用于設(shè)置幀的刷新 FPS = 40 clock = pygame.time.Clock() # 創(chuàng)建用戶自定義事件,每隔2000毫秒觸發(fā)一次事件,隨機(jī)創(chuàng)建敵人 CREATE_ENEMY = pygame.USEREVENT # 每隔2000毫秒,會(huì)傳遞一個(gè)信號(hào) pygame.time.set_timer(CREATE_ENEMY, 2000) # 對(duì)于精靈定義了主角,子彈,敵人,爆炸,可移動(dòng)背景四個(gè)。 #class Hero(pygame.sprite.Sprite) #class Bullet(pygame.sprite.Sprite) #class Enemy(pygame.sprite.Sprite) #class Explode(pygame.sprite.Sprite) #class BackGround(pygame.sprite.Sprite) # 主角 class Hero(pygame.sprite.Sprite): def __init__(self, speed): super().__init__() # 調(diào)用父類的初始化方法 self.image = pygame.image.load('./image/plane.png') self.rect = self.image.get_rect() # 對(duì)圖片進(jìn)行一些尺寸處理 self.rect.width *= 0.5 self.rect.height *= 0.5 self.image = pygame.transform.scale(self.image, (self.rect.width, self.rect.height)) # 主角初始化位置 self.rect.x, self.rect.y = 0, 100 self.speed = speed self.ready_to_fire = 0 def update(self, *args): keys = pygame.key.get_pressed() if keys[pygame.K_UP]: self.rect.y -= self.speed if keys[pygame.K_DOWN]: self.rect.y += self.speed if keys[pygame.K_LEFT]: self.rect.x -= self.speed if keys[pygame.K_RIGHT]: self.rect.x += self.speed if keys[pygame.K_SPACE]: if self.ready_to_fire == 0: self.fire() self.ready_to_fire += 1 if self.ready_to_fire > 5: self.ready_to_fire = 0 else: self.ready_to_fire = 0 if self.rect.x < 0: self.rect.x = 0 if self.rect.y < 0: self.rect.y = 0 if self.rect.y > HEIGHT - self.rect.height: self.rect.y = HEIGHT - self.rect.height # 子彈發(fā)射 def fire(self): bullet = Bullet(10) bullet.rect.x = self.rect.right bullet.rect.centery = self.rect.centery bullet_sprite.add(bullet) # 音效 sound = pygame.mixer.Sound('./sound/laser.wav') sound.play() class Bullet(pygame.sprite.Sprite): def __init__(self, speed): super().__init__() self.image = pygame.image.load('./image/bullet.png') self.rect = self.image.get_rect() self.speed = speed def update(self, *args): self.rect.x += self.speed if self.rect.x > WIDTH: self.kill() class Enemy(pygame.sprite.Sprite): def __init__(self, speed): super().__init__() self.image = pygame.image.load('./image/enemy1.png') self.rect = self.image.get_rect() self.rect.x = 800 self.rect.y = random.randint(0, HEIGHT) self.speed = speed def update(self, *args): self.rect.x -= self.speed if self.rect.right < 0: self.kill() class Explode(pygame.sprite.Sprite): def __init__(self): super().__init__() self.images = [pygame.image.load('./image/explode' + str(i) + '.png') for i in range(1, 4)] self.image_index = 0 self.image = self.images[self.image_index] self.rect = self.image.get_rect() self.readt_to_change = 0 sound = pygame.mixer.Sound('./sound/enemyExplode.wav') sound.play() def update(self, *args): if self.image_index < 2: self.readt_to_change += 1 if self.readt_to_change % 4 == 0: self.image_index += 1 self.image = self.images[self.image_index] else: self.kill() class BackGround(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image = pygame.image.load('./image/background.jpg') self.rect = self.image.get_rect() self.ready_to_move = 0 def update(self, *args): self.rect.x -= 3 if self.rect.right <= 0: self.rect.x = self.rect.width # 初始化精靈組 bg_sprite = pygame.sprite.Group() hero_sprite = pygame.sprite.Group() enemy_sprite = pygame.sprite.Group() bullet_sprite = pygame.sprite.Group() explode_sprite = pygame.sprite.Group() # 定義人物 hero1 = Hero(4) hero_sprite.add(hero1) enemy1 = Enemy(5) enemy2 = Enemy(7) bg1 = BackGround() bg2 = BackGround() bg2.rect.x = bg2.rect.width bg_sprite.add(bg1, bg2) # 保持游戲運(yùn)行狀態(tài)(游戲循環(huán)) while True: # ===========游戲幀的刷新=========== clock.tick(FPS) # 檢測(cè)事件 for event in pygame.event.get(): # 檢測(cè)關(guān)閉按鈕被點(diǎn)擊的事件 if event.type == pygame.QUIT: # 退出 pygame.quit() exit() if event.type == CREATE_ENEMY: enemy_sprite.add(Enemy(random.randint(1, 7))) # 碰撞檢測(cè),返回字典,得到二者信息 collision = pygame.sprite.groupcollide(enemy_sprite, bullet_sprite, True, True) for enemy in collision.keys(): explode = Explode() explode.rect = enemy.rect explode_sprite.add(explode) # screen.fill((0,0,0)) for group in [bg_sprite, hero_sprite, enemy_sprite, bullet_sprite, explode_sprite]: group.update() group.draw(screen) pygame.display.update()
到此這篇關(guān)于Python+Pygame實(shí)現(xiàn)懷舊游戲飛機(jī)大戰(zhàn)的文章就介紹到這了,更多相關(guān)Python Pygame飛機(jī)大戰(zhàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python?異步之如何啟動(dòng)獲取事件循環(huán)
這篇文章主要為大家介紹了Python?異步之如何啟動(dòng)獲取事件循環(huán)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Python存儲(chǔ)與讀寫二進(jìn)制文件的示例代碼
本文介紹了如何在Python中使用Numpy將數(shù)組轉(zhuǎn)存為二進(jìn)制文件,并通過內(nèi)存映射的方式讀取,提供了一個(gè)高效處理大量數(shù)據(jù)的方法,示例代碼展示了完整的存儲(chǔ)和讀取過程,解釋了頁(yè)大小和數(shù)據(jù)存儲(chǔ)的關(guān)系,適用于需要高性能計(jì)算和數(shù)據(jù)壓縮的場(chǎng)景,感興趣的朋友跟隨小編一起看看吧2024-09-09Python中將圖像轉(zhuǎn)換為PDF的方法實(shí)現(xiàn)
本文主要介紹了Python中將圖像轉(zhuǎn)換為PDF的方法實(shí)現(xiàn),主要使用img2pdf和PyPDF2軟件包,具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08python opencv 圖像處理之圖像算數(shù)運(yùn)算及修改顏色空間
這篇文章主要介紹了python opencv 圖像處理之圖像算數(shù)運(yùn)算及修改顏色空間,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08如何利用Python快速統(tǒng)計(jì)文本的行數(shù)
這篇文章主要介紹了如何利用Python快速統(tǒng)計(jì)文本的行數(shù),要快速統(tǒng)計(jì)一個(gè)文本文件中的行數(shù),其實(shí)就是要統(tǒng)計(jì)這個(gè)文本文件中換行符的個(gè)數(shù),下面我們就一起進(jìn)入文章看看具體的操作過程吧2021-12-12python3 實(shí)現(xiàn)函數(shù)寫文件路徑的正確方法
今天小編就為大家分享一篇python3 實(shí)現(xiàn)函數(shù)寫文件路徑的正確方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-11-11詳解Python排序算法的實(shí)現(xiàn)(冒泡,選擇,插入,快速)
這篇文章主要為大家介紹了Python中常見的四種排序算法的實(shí)現(xiàn):冒泡排序、選擇排序、插入排序和快速排序,文中通過圖片詳細(xì)講解了它們實(shí)現(xiàn)的原理與代碼,需要的可以參考一下2022-04-04