用Python實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的完整代碼
飛機(jī)大戰(zhàn)是個(gè)什么樣的小游戲呢?
首先我們需要有一個(gè)自己的飛機(jī),它可以在畫(huà)面上進(jìn)行上下左右移動(dòng),我們通過(guò)方向鍵來(lái)控制它的移動(dòng),我們的飛機(jī)要發(fā)射子彈,用來(lái)?yè)舸驍硻C(jī),我們用空格鍵來(lái)控制子彈的發(fā)射
然后需要設(shè)置敵機(jī),隨機(jī)出現(xiàn)在畫(huà)面上,以一定的速度向下移動(dòng) 敵機(jī)和我們自己的飛機(jī)相撞時(shí)游戲結(jié)束
游戲結(jié)束時(shí)統(tǒng)計(jì)得分,擊落一只敵機(jī)得10分
至此,我們一個(gè)飛機(jī)大戰(zhàn)的小游戲就設(shè)計(jì)完成了!那么,要如何實(shí)現(xiàn)呢?
上完整代碼:
# air_shoot.py
# 飛機(jī)大戰(zhàn)小游戲
import pygame
import random
import sys
# 初始化 Pygame
pygame.init()
# 屏幕大小
WIDTH, HEIGHT = 480, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("plane war")
# 顏色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# 時(shí)鐘(控制幀率)
clock = pygame.time.Clock()
# 字體
font = pygame.font.SysFont("simhei", 32) # 如果報(bào)錯(cuò),改為 None 或 "Arial"
small_font = pygame.font.SysFont("simhei", 24)
# 玩家飛機(jī)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH // 2
self.rect.bottom = HEIGHT - 10
self.speed = 5
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < WIDTH:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < HEIGHT:
self.rect.y += self.speed
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
# 敵機(jī)
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, WIDTH - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(2, 5)
def update(self):
self.rect.y += self.speed
if self.rect.top > HEIGHT:
self.kill() # 移出屏幕后刪除
# 子彈
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill()
# 顯示文字
def draw_text(surf, text, font, x, y, color=WHITE):
img = font.render(text, True, color)
rect = img.get_rect()
rect.midtop = (x, y)
surf.blit(img, rect)
# 游戲結(jié)束畫(huà)面
def show_game_over(score):
screen.fill(BLACK)
draw_text(screen, "GAME OVER", font, WIDTH//2, HEIGHT//2 - 50, RED)
draw_text(screen, f"SCORE: {score}", small_font, WIDTH//2, HEIGHT//2)
draw_text(screen, "press R restart, Q quit", small_font, WIDTH//2, HEIGHT//2 + 50)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
waiting = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
# 主游戲函數(shù)
def game():
global all_sprites, bullets, enemies
all_sprites = pygame.sprite.Group()
bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
score = 0
enemy_spawn_rate = 30 # 幀數(shù)(越小越密集)
running = True
while running:
clock.tick(60)
current_frame = pygame.time.get_ticks() // 1000 * 60 # 當(dāng)前幀數(shù)(粗略)
# 事件處理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 按鍵射擊(長(zhǎng)按連續(xù)發(fā)射)
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if len(bullets) < 5: # 限制子彈數(shù)量
player.shoot()
# 生成敵機(jī)
if random.randint(1, enemy_spawn_rate) == 1:
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# 更新所有精靈
all_sprites.update()
# 子彈擊中敵機(jī)
hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
for hit in hits:
score += 10
# 玩家與敵機(jī)碰撞
if pygame.sprite.spritecollide(player, enemies, False):
running = False
# 繪制
screen.fill(BLACK)
all_sprites.draw(screen)
draw_text(screen, f"score: {score}", small_font, 60, 10)
pygame.display.flip()
# 游戲結(jié)束
show_game_over(score)
# 主循環(huán)(支持重玩)
while True:
game()
游戲整體結(jié)構(gòu)
這個(gè)游戲使用了 Pygame 框架 和 面向?qū)ο缶幊蹋∣OP) 的方式來(lái)組織代碼。主要分為以下幾個(gè)部分:
- 初始化設(shè)置
- 定義游戲?qū)ο箢悾ㄍ婕?、敵機(jī)、子彈)
- 游戲主循環(huán)
- 碰撞檢測(cè)與得分
- 游戲結(jié)束界面
- 支持重玩機(jī)制
第一部分:導(dǎo)入模塊和初始化
import pygame import random import sys
pygame:核心游戲庫(kù)。random:用于生成隨機(jī)位置、速度等。sys:用于安全退出程序。
pygame.init()
初始化所有 Pygame 的模塊(如聲音、顯示、字體等),這是使用 Pygame 的第一步。
WIDTH, HEIGHT = 480, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("飛機(jī)大戰(zhàn)")
- 設(shè)置窗口大小為 480×600 像素。
- 創(chuàng)建一個(gè)顯示窗口,并設(shè)置標(biāo)題為“飛機(jī)大戰(zhàn)”。
WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0)
定義顏色常量。Pygame 中顏色用 RGB 元組表示:
(255, 255, 255)是白色(0, 0, 0)是黑色(255, 0, 0)是紅色(敵機(jī))(0, 255, 0)是綠色(玩家)
clock = pygame.time.Clock()
創(chuàng)建一個(gè)時(shí)鐘對(duì)象,用來(lái)控制游戲幀率(FPS),防止運(yùn)行過(guò)快或過(guò)慢。
font = pygame.font.SysFont("simhei", 32)
small_font = pygame.font.SysFont("simhei", 24)
創(chuàng)建字體對(duì)象,用于在屏幕上繪制文字。
"simhei"是黑體,支持中文。- 如果系統(tǒng)沒(méi)有這個(gè)字體,可以用
'Arial'或None替代。
第二部分:定義游戲角色類
1. 玩家飛機(jī)類Player
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH // 2
self.rect.bottom = HEIGHT - 10
self.speed = 5
- 繼承自
pygame.sprite.Sprite—— 這是 Pygame 中所有可移動(dòng)對(duì)象的基礎(chǔ)類。 image:角色的外觀,這里是一個(gè)綠色矩形(50寬 × 40高)。rect:角色的位置和邊界框。- 初始位置:水平居中,底部距離屏幕底邊 10 像素。
speed:移動(dòng)速度。
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < WIDTH:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < HEIGHT:
self.rect.y += self.speed
每一幀調(diào)用一次
update()方法:
- 獲取當(dāng)前按下的按鍵狀態(tài)。
- 控制方向鍵移動(dòng)。
- 加入邊界判斷,不讓飛機(jī)飛出窗口。
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
發(fā)射子彈的方法:
- 在飛機(jī)頂部中心創(chuàng)建一顆子彈。
- 把它加入總精靈組
all_sprites和子彈組bullets,以便更新和繪制。
2. 敵機(jī)類Enemy
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, WIDTH - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(2, 5)
- 紅色矩形代表敵機(jī)。
- 出現(xiàn)在屏幕上方(y 為負(fù)值),從不同 x 位置隨機(jī)出現(xiàn)。
- 下落速度隨機(jī)(2~5像素/幀)。
def update(self):
self.rect.y += self.speed
if self.rect.top > HEIGHT:
self.kill() # 移出屏幕后刪除
敵機(jī)持續(xù)下落,一旦完全移出屏幕底部就自動(dòng)銷毀(
kill()),避免內(nèi)存泄漏。
3. 子彈類Bullet
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10 # 負(fù)數(shù)表示向上飛
- 白色小矩形表示子彈。
- 從玩家飛機(jī)頂部發(fā)射。
- 向上飛行(
speed = -10)。
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill() # 子彈飛出屏幕頂端就銷毀
第三部分:輔助函數(shù)
顯示文字函數(shù)
def draw_text(surf, text, font, x, y, color=WHITE):
img = font.render(text, True, color)
rect = img.get_rect()
rect.midtop = (x, y)
surf.blit(img, rect)
封裝了一個(gè)通用的文字繪制函數(shù):
surf:要畫(huà)在哪(通常是screen)text:要顯示的文字font:字體對(duì)象(x, y):文字左上角坐標(biāo)blit():把文字圖像畫(huà)到屏幕上
游戲結(jié)束畫(huà)面
def show_game_over(score):
screen.fill(BLACK)
draw_text(screen, "游戲結(jié)束", font, WIDTH//2, HEIGHT//2 - 50, RED)
draw_text(screen, f"得分: {score}", small_font, WIDTH//2, HEIGHT//2)
draw_text(screen, "按 R 重新開(kāi)始,Q 退出", small_font, WIDTH//2, HEIGHT//2 + 50)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
waiting = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
顯示“游戲結(jié)束”界面并等待用戶選擇:
- 填黑背景,顯示得分。
- 提示按 R 重玩,Q 退出。
- 使用一個(gè)循環(huán)等待輸入,直到用戶決定。
第四部分:主游戲函數(shù)game()
def game():
global all_sprites, bullets, enemies
all_sprites = pygame.sprite.Group()
bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
score = 0
enemy_spawn_rate = 30 # 每30幀左右生成一架敵機(jī)
running = True
初始化游戲狀態(tài):
- 創(chuàng)建三個(gè)精靈組:
all_sprites:所有要繪制和更新的對(duì)象bullets:所有子彈enemies:所有敵機(jī)
- 添加玩家
- 得分從 0 開(kāi)始
while running:
clock.tick(60) # 鎖定60 FPS
# 事件處理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
主循環(huán)每秒運(yùn)行約 60 次(由
clock.tick(60)控制)。
處理退出事件。
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if len(bullets) < 5: # 限制最多5發(fā)子彈
player.shoot()
檢測(cè)是否按下空格鍵,如果是且子彈不多于5個(gè),則發(fā)射。
# 生成敵機(jī)
if random.randint(1, enemy_spawn_rate) == 1:
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
隨機(jī)生成敵機(jī)(大約每 30 幀生成一架)。
all_sprites.update()
更新所有精靈的位置(包括玩家、敵機(jī)、子彈)。
# 子彈擊中敵機(jī)
hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
for hit in hits:
score += 10
groupcollide()自動(dòng)檢測(cè)兩組精靈之間的碰撞:
- 子彈打中敵機(jī) → 雙方都銷毀(
True, True) - 每消滅一個(gè)敵機(jī)加 10 分
# 玩家與敵機(jī)碰撞
if pygame.sprite.spritecollide(player, enemies, False):
running = False
如果玩家碰到任何敵機(jī)(即使只是擦邊),游戲結(jié)束。
# 繪制畫(huà)面
screen.fill(BLACK)
all_sprites.draw(screen)
draw_text(screen, f"得分: {score}", small_font, 60, 10)
pygame.display.flip()
清屏 → 畫(huà)所有精靈 → 顯示得分 → 刷新屏幕
show_game_over(score) # 游戲結(jié)束后顯示結(jié)束畫(huà)面
第五部分:支持重復(fù)游戲
while True:
game()
主循環(huán)外再套一層
while True,這樣每次游戲結(jié)束后都可以重新開(kāi)始。
總結(jié):游戲運(yùn)行流程圖
開(kāi)始游戲 ↓ 初始化 Pygame 和變量 ↓ 進(jìn)入 game() 函數(shù) ↓ 創(chuàng)建玩家和精靈組 ↓ 主循環(huán): → 處理事件(退出、按鍵) → 玩家移動(dòng)/射擊 → 隨機(jī)生成敵機(jī) → 更新所有精靈位置 → 檢測(cè)碰撞(子彈打敵機(jī)、玩家撞敵機(jī)) → 繪制畫(huà)面和得分 ↓ 玩家被撞 → 結(jié)束主循環(huán) ↓ 調(diào)用 show_game_over() ↓ 等待用戶按 R 或 Q → 按 R:回到 game() 重新開(kāi)始 → 按 Q:退出程序
后續(xù)擴(kuò)展建議
你可以基于這個(gè)框架繼續(xù)添加功能:
| 功能 | 實(shí)現(xiàn)思路 |
|---|---|
| 添加音效 | 使用 pygame.mixer.Sound() 播放射擊、爆炸音效 |
| 使用圖片代替方塊 | pygame.image.load("player.png") |
| 添加爆炸動(dòng)畫(huà) | 碰撞時(shí)播放一系列圖片 |
| 生命值系統(tǒng) | 玩家可承受多次撞擊 |
| 道具掉落 | 敵機(jī)死亡時(shí)隨機(jī)掉落加速、多子彈等道具 |
到此這篇關(guān)于用Python實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲的文章就介紹到這了,更多相關(guān)Python飛機(jī)大戰(zhàn)小游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python經(jīng)典趣味24點(diǎn)游戲程序設(shè)計(jì)
這篇文章主要介紹了python經(jīng)典趣味24點(diǎn)游戲程序設(shè)計(jì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
分享unittest單元測(cè)試框架中幾種常用的用例加載方法
這篇文章主要介紹了unittest單元測(cè)試框架中常用的幾種用例加載方法,幫助大家更好的理解和使用python的unittest測(cè)試模塊,感興趣的朋友可以了解下2020-12-12
python實(shí)現(xiàn)淘寶購(gòu)物系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)易的淘寶購(gòu)物系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
Python 多線程搜索txt文件的內(nèi)容,并寫(xiě)入搜到的內(nèi)容(Lock)方法
今天小編就為大家分享一篇Python 多線程搜索txt文件的內(nèi)容,并寫(xiě)入搜到的內(nèi)容(Lock)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08
使用selenium模擬登錄解決滑塊驗(yàn)證問(wèn)題的實(shí)現(xiàn)
這篇文章主要介紹了使用selenium模擬登錄解決滑塊驗(yàn)證問(wèn)題的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
python安裝并使用virtualenv管理包的詳細(xì)過(guò)程
本文主要介紹了Python的安裝過(guò)程和如何使用virtualenv管理包,首先,用戶需要訪問(wèn)Python官網(wǎng)下載安裝包,并運(yùn)行安裝程序,安裝完成后,在命令行輸入Python,顯示安裝的Python版本號(hào),即表示安裝成功,感興趣的朋友一起看看吧2024-10-10
python免殺技術(shù)shellcode的加載與執(zhí)行
本文主要介紹了python免殺技術(shù)shellcode的加載與執(zhí)行,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
python簡(jiǎn)單實(shí)現(xiàn)獲取當(dāng)前時(shí)間
最近項(xiàng)目中經(jīng)常需要python去取當(dāng)前的時(shí)間,雖然不是很難,但是老是忘記,用一次丟一次,為了能夠更好的記住,我今天特意寫(xiě)下python 當(dāng)前時(shí)間這篇文章,如果你覺(jué)的對(duì)你有用的話,可以收藏下。2016-08-08

