【Python實戰】飛機大戰

開發一個飛機大戰游戲是Python學習的經典實戰項目,尤其適合結合面向對象編程和游戲框架(如Pygame)進行實踐。以下是游戲設計的核心考慮因素和模塊劃分建議:


一、游戲設計核心考慮因素

  1. 性能優化

    • Python游戲需注意幀率控制(如60FPS)
    • 避免頻繁的對象創建/銷毀(使用對象池管理子彈、敵機)
    • 減少圖像縮放等實時計算操作(預加載縮放后的圖片)
  2. 游戲循環(Game Loop)

    • 主循環需要處理:事件監聽→狀態更新→畫面渲染→音效播放
    • 控制循環頻率(如pygame.time.Clock().tick(60)
  3. 輸入控制

    • 響應鍵盤事件(WSAD/方向鍵移動,空格發射子彈)
    • 支持手柄輸入(可選擴展)
  4. 碰撞檢測

    • 使用矩形碰撞(pygame.Rect.colliderect
    • 優化檢測效率(分組檢測:玩家子彈 vs 敵機、敵機 vs 玩家)
  5. 游戲狀態管理

    • 區分不同場景:開始界面、游戲中、暫停、結束界面
    • 使用狀態機或場景堆棧管理(如game_state = "playing"
  6. 資源管理

    • 集中加載圖片、音效、字體(避免重復IO操作)
    • 使用相對路徑確保跨平臺兼容性
  7. 可擴展性

    • 模塊化設計,方便新增敵機類型、武器系統
    • 配置數據分離(如敵機屬性存于JSON文件)

二、游戲核心模塊劃分

1. 游戲主模塊(Main Game)
# ====================== 游戲主邏輯 ======================
class Game:def __init__(self):# 初始化顯示self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("飛機大戰")self.clock = pygame.time.Clock()# 加載資源self.load_resources()# 游戲狀態self.running = Trueself.score = 0def load_resources(self):"""加載所有資源"""global shoot_sound, explosion_soundshoot_sound = load_sound("pew.wav")explosion_sound = load_sound("expl3.wav")# 初始化精靈組self.all_sprites = pygame.sprite.Group()self.enemies = pygame.sprite.Group()self.bullets = pygame.sprite.Group()# 創建玩家self.player = Player()self.all_sprites.add(self.player)# 創建敵機組self.enemy_spawn_timer = pygame.USEREVENT + 1pygame.time.set_timer(self.enemy_spawn_timer, 1000)  # 每秒生成敵機def handle_events(self):"""處理事件循環"""for event in pygame.event.get():if event.type == pygame.QUIT:self.running = Falseelif event.type == pygame.KEYDOWN:if event.key == pygame.K_ESCAPE:self.running = Falseelif event.type == self.enemy_spawn_timer:enemy = Enemy()self.all_sprites.add(enemy)self.enemies.add(enemy)def check_collisions(self):"""檢測碰撞事件"""# 子彈擊中敵機hits = pygame.sprite.groupcollide(self.enemies, self.bullets, True, True)for hit in hits:self.score += 50explosion_sound.play()# 敵機撞擊玩家hits = pygame.sprite.spritecollide(self.player, self.enemies, True)for hit in hits:self.player.health -= 1if self.player.health <= 0:self.game_over()def draw_hud(self):"""繪制游戲界面HUD"""# 繪制得分font = pygame.font.Font(None, 36)score_text = font.render(f"Score: {self.score}", True, WHITE)self.screen.blit(score_text, (10, 10))# 繪制生命值health_text = font.render(f"Health: {self.player.health}", True, RED)self.screen.blit(health_text, (10, 50))def game_over(self):"""游戲結束處理"""font = pygame.font.Font(None, 74)text = font.render("GAME OVER", True, RED)text_rect = text.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))self.screen.blit(text, text_rect)pygame.display.flip()pygame.time.wait(10000)  # 等待2秒self.running = Falsedef run(self):"""游戲主循環"""while self.running:# 控制幀率self.clock.tick(FPS)# 處理輸入self.handle_events()keys = pygame.key.get_pressed()if keys[pygame.K_SPACE]:self.player.shoot(self.bullets, self.all_sprites)# 更新游戲狀態self.all_sprites.update(keys)  # 更新所有精靈self.check_collisions()# 渲染畫面self.screen.fill(BLACK)self.all_sprites.draw(self.screen)self.draw_hud()pygame.display.flip()pygame.quit()
2. 精靈類(Sprites)

使用面向對象設計游戲元素:

  • Player(玩家飛機)

      """玩家飛機類"""def __init__(self):super().__init__()self.image = load_image("player.png")self.rect = self.image.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT - 50))self.speed = PLAYER_SPEEDself.health = 3self.shoot_delay = 250  # 射擊間隔(毫秒)self.last_shot = pygame.time.get_ticks()def update(self, keys):"""根據鍵盤輸入更新位置"""# 水平移動if keys[pygame.K_LEFT] or keys[pygame.K_a]:self.rect.x -= self.speedif keys[pygame.K_RIGHT] or keys[pygame.K_d]:self.rect.x += self.speed# 垂直移動(可選)if keys[pygame.K_UP] or keys[pygame.K_w]:self.rect.y -= self.speedif keys[pygame.K_DOWN] or keys[pygame.K_s]:self.rect.y += self.speed# 邊界約束self.rect.clamp_ip(pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))def shoot(self, bullets, all_sprites):"""發射子彈"""now = pygame.time.get_ticks()if now - self.last_shot > self.shoot_delay:self.last_shot = nowbullet = Bullet(self.rect.centerx, self.rect.top)all_sprites.add(bullet)bullets.add(bullet)shoot_sound.play()
    
  • Enemy(敵機)

      def __init__(self):super().__init__()self.image = load_image("enemy1.png")self.rect = self.image.get_rect()self.rect = self.image.get_rect(x=random.randrange(SCREEN_WIDTH - self.rect.width),y=random.randrange(-100, -40),)self.speed_y = random.randint(*ENEMY_SPEED_RANGE)self.speed_x = random.choice([-1, 0, 1])  # 橫向移動def update(self, *args):"""自動向下移動"""self.rect.y += self.speed_yself.rect.x += self.speed_x# 移出屏幕后刪除if self.rect.top > SCREEN_HEIGHT + 10:self.kill()
    
  • Bullet(子彈)

      def __init__(self, x, y):super().__init__()self.image = load_image("bullet3.png")self.rect = self.image.get_rect(center=(x, y))self.speed_y = BULLET_SPEEDdef update(self, *args):"""向上移動"""self.rect.y += self.speed_yif self.rect.bottom < 0:  # 移出屏幕后刪除self.kill()
    

三、推薦技術棧

  1. 游戲框架

    • Pygame:最適合2D游戲入門,文檔豐富
      Pygame官方文檔
    • Arcade:現代Python游戲庫,面向對象更友好
      Arcade官網
  2. 素材資源

    • 免費素材網站:OpenGameArt、Kenney Assets
    • 臨時占位素材:可用簡單幾何圖形代替
  3. 代碼結構參考

    • GitHub經典項目:pygame-shmup
    • 教程:Pygame飛機大戰教程

四、開發路線建議

  1. 基礎版本(1-3天)

    • 實現玩家移動、發射子彈
    • 隨機生成敵機,碰撞檢測得分
    • 顯示血量和分數
  2. 進階版本(3-7天)

    • 添加不同敵機類型(普通/快速/BOSS)
    • 實現敵機發射子彈
    • 增加音效和爆炸動畫
    • 支持游戲暫停/繼續
  3. 擴展版本(可選)

    • 添加道具系統(護盾、連發武器)
    • 實現關卡進度和難度曲線
    • 支持本地高分榜(SQLite存儲)
    • 打包為exe/APK文件

五、避坑指南

  1. 不要過早優化:先完成核心玩法,再考慮性能
  2. 善用精靈組(Sprite Groups)pygame.sprite.Group()管理同類對象
  3. 坐標系注意:Pygame的Y軸向下增大(與數學坐標系相反)
  4. 資源路徑問題:使用os.path處理路徑,避免絕對路徑硬編碼
  5. 調試技巧:用print輸出變量或繪制調試矩形(pygame.draw.rect

通過分階段實現,你將逐步掌握游戲開發的核心模式(狀態機、對象池、事件驅動),同時鞏固Python面向對象編程和模塊化設計能力。

六、總體代碼(單文件)

# -*- coding: utf-8 -*-
import pygame
import random
import os# 初始化Pygame和混音器
pygame.init()
pygame.mixer.init()# 游戲常量配置
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 600
FPS = 60
PLAYER_SPEED = 5
ENEMY_SPEED_RANGE = (2, 4)
BULLET_SPEED = -8  # 玩家子彈速度(向上)# 顏色定義
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)# 資源路徑配置
game_folder = os.path.dirname(__file__)
img_folder = os.path.join(game_folder, "images")
snd_folder = os.path.join(game_folder, "sounds")# 加載圖形資源
def load_image(file):"""加載圖像并轉換格式,返回圖像和矩形"""path = os.path.join(img_folder, file)try:image = pygame.image.load(path).convert()except pygame.error as e:print(f"無法加載圖像: {path}")raise SystemExit(e)image.set_colorkey(BLACK)  # 設置透明色return image# 加載音效資源
def load_sound(file):"""加載音效文件"""path = os.path.join(snd_folder, file)try:return pygame.mixer.Sound(path)except pygame.error as e:print(f"無法加載音效: {path}")return None# ====================== 游戲精靈類 ======================
class Player(pygame.sprite.Sprite):"""玩家飛機類"""def __init__(self):super().__init__()self.image = load_image("player.png")self.rect = self.image.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT - 50))self.speed = PLAYER_SPEEDself.health = 3self.shoot_delay = 250  # 射擊間隔(毫秒)self.last_shot = pygame.time.get_ticks()def update(self, keys):"""根據鍵盤輸入更新位置"""# 水平移動if keys[pygame.K_LEFT] or keys[pygame.K_a]:self.rect.x -= self.speedif keys[pygame.K_RIGHT] or keys[pygame.K_d]:self.rect.x += self.speed# 垂直移動(可選)if keys[pygame.K_UP] or keys[pygame.K_w]:self.rect.y -= self.speedif keys[pygame.K_DOWN] or keys[pygame.K_s]:self.rect.y += self.speed# 邊界約束self.rect.clamp_ip(pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))def shoot(self, bullets, all_sprites):"""發射子彈"""now = pygame.time.get_ticks()if now - self.last_shot > self.shoot_delay:self.last_shot = nowbullet = Bullet(self.rect.centerx, self.rect.top)all_sprites.add(bullet)bullets.add(bullet)shoot_sound.play()class Enemy(pygame.sprite.Sprite):"""敵機基類"""def __init__(self):super().__init__()self.image = load_image("enemy1.png")self.rect = self.image.get_rect()self.rect = self.image.get_rect(x=random.randrange(SCREEN_WIDTH - self.rect.width),y=random.randrange(-100, -40),)self.speed_y = random.randint(*ENEMY_SPEED_RANGE)self.speed_x = random.choice([-1, 0, 1])  # 橫向移動def update(self, *args):"""自動向下移動"""self.rect.y += self.speed_yself.rect.x += self.speed_x# 移出屏幕后刪除if self.rect.top > SCREEN_HEIGHT + 10:self.kill()class Bullet(pygame.sprite.Sprite):"""玩家子彈類"""def __init__(self, x, y):super().__init__()self.image = load_image("bullet3.png")self.rect = self.image.get_rect(center=(x, y))self.speed_y = BULLET_SPEEDdef update(self, *args):"""向上移動"""self.rect.y += self.speed_yif self.rect.bottom < 0:  # 移出屏幕后刪除self.kill()# ====================== 游戲主邏輯 ======================
class Game:def __init__(self):# 初始化顯示self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("飛機大戰")self.clock = pygame.time.Clock()# 加載資源self.load_resources()# 游戲狀態self.running = Trueself.score = 0def load_resources(self):"""加載所有資源"""global shoot_sound, explosion_soundshoot_sound = load_sound("pew.wav")explosion_sound = load_sound("expl3.wav")# 初始化精靈組self.all_sprites = pygame.sprite.Group()self.enemies = pygame.sprite.Group()self.bullets = pygame.sprite.Group()# 創建玩家self.player = Player()self.all_sprites.add(self.player)# 創建敵機組self.enemy_spawn_timer = pygame.USEREVENT + 1pygame.time.set_timer(self.enemy_spawn_timer, 1000)  # 每秒生成敵機def handle_events(self):"""處理事件循環"""for event in pygame.event.get():if event.type == pygame.QUIT:self.running = Falseelif event.type == pygame.KEYDOWN:if event.key == pygame.K_ESCAPE:self.running = Falseelif event.type == self.enemy_spawn_timer:enemy = Enemy()self.all_sprites.add(enemy)self.enemies.add(enemy)def check_collisions(self):"""檢測碰撞事件"""# 子彈擊中敵機hits = pygame.sprite.groupcollide(self.enemies, self.bullets, True, True)for hit in hits:self.score += 50explosion_sound.play()# 敵機撞擊玩家hits = pygame.sprite.spritecollide(self.player, self.enemies, True)for hit in hits:self.player.health -= 1if self.player.health <= 0:self.game_over()def draw_hud(self):"""繪制游戲界面HUD"""# 繪制得分font = pygame.font.Font(None, 36)score_text = font.render(f"Score: {self.score}", True, WHITE)self.screen.blit(score_text, (10, 10))# 繪制生命值health_text = font.render(f"Health: {self.player.health}", True, RED)self.screen.blit(health_text, (10, 50))def game_over(self):"""游戲結束處理"""font = pygame.font.Font(None, 74)text = font.render("GAME OVER", True, RED)text_rect = text.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))self.screen.blit(text, text_rect)pygame.display.flip()pygame.time.wait(10000)  # 等待2秒self.running = Falsedef run(self):"""游戲主循環"""while self.running:# 控制幀率self.clock.tick(FPS)# 處理輸入self.handle_events()keys = pygame.key.get_pressed()if keys[pygame.K_SPACE]:self.player.shoot(self.bullets, self.all_sprites)# 更新游戲狀態self.all_sprites.update(keys)  # 更新所有精靈self.check_collisions()# 渲染畫面self.screen.fill(BLACK)self.all_sprites.draw(self.screen)self.draw_hud()pygame.display.flip()pygame.quit()if __name__ == "__main__":game = Game()game.run()

附件:圖片資源

請添加圖片描述
請添加圖片描述
請添加圖片描述

音效資源無法放置在此處,如自行下載。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79326.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79326.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79326.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flowable7.x學習筆記(十八)拾取我的待辦

前言 本文從解讀源碼到實現功能&#xff0c;完整的學習Flowable的【TaskService】-【claim】方法實現的任務拾取功能。 一、概述 當調用 TaskService.claim(taskId, userId) 時&#xff0c;Flowable 會先加載并校驗任務實體&#xff0c;再判斷該任務是否已被認領&#xff1b;若…

SQL經典實例

第1章 檢索記錄 1.1 檢索所有行和列 知識點&#xff1a;使用SELECT *快速檢索表中所有列&#xff1b;顯式列出列名&#xff08;如SELECT col1, col2&#xff09;提高可讀性和可控性&#xff0c;尤其在編程場景中更清晰。 1.2 篩選行 知識點&#xff1a;通過WHERE子句過濾符合條…

HTTPcookie與session實現

1.HTTP Cookie 定義 HTTP Cookie &#xff08;也稱為 Web Cookie 、瀏覽器 Cookie 或簡稱 Cookie &#xff09;是服務器發送到 用戶瀏覽器并保存在瀏覽器上的一小塊數據&#xff0c;它會在瀏覽器之后向同一服務器再次發 起請求時被攜帶并發送到服務器上。通常&#xff0…

【算法基礎】冒泡排序算法 - JAVA

一、算法基礎 1.1 什么是冒泡排序 冒泡排序是一種簡單直觀的比較排序算法。它重復地走訪待排序的數列&#xff0c;依次比較相鄰兩個元素&#xff0c;如果順序錯誤就交換它們&#xff0c;直到沒有元素需要交換為止。 1.2 基本思想 比較相鄰元素&#xff1a;從頭開始&#xf…

0902Redux_狀態管理-react-仿低代碼平臺項目

文章目錄 1 Redux 概述1.1 核心概念1.2 基本組成1.3 工作流程1.4 中間件&#xff08;Middleware&#xff09;1.5 適用場景1.6 優缺點1.7 Redux Toolkit&#xff08;現代推薦&#xff09;1.8 與其他工具的對比1.9 總結 2 todoList 待辦事項案例3 Redux開發者工具3.1 核心功能3.2…

《ATPL地面培訓教材13:飛行原理》——第6章:阻力

翻譯&#xff1a;Leweslyh&#xff1b;工具&#xff1a;Cursor & Claude 3.7&#xff1b;過程稿 第6章&#xff1a;阻力 目錄 引言寄生阻力誘導阻力減少誘導阻力的方法升力對寄生阻力的影響飛機總阻力飛機總重量對總阻力的影響高度對總阻力的影響構型對總阻力的影響速度穩…

C++總結01-類型相關

一、數據存儲 1.程序數據段 ? 靜態&#xff08;全局&#xff09;數據區&#xff1a;全局變量、靜態變量 ? 堆內存&#xff1a;程序員手動分配、手動釋放 ? 棧內存&#xff1a;編譯器自動分配、自動釋放 ? 常量區&#xff1a;編譯時大小、值確定不可修改 2.程序代碼段 ?…

【Hot 100】94. 二叉樹的中序遍歷

目錄 引言二叉樹的中序遍歷我的解題代碼優化更清晰的表述建議&#xff1a; &#x1f64b;?♂? 作者&#xff1a;海碼007&#x1f4dc; 專欄&#xff1a;算法專欄&#x1f4a5; 標題&#xff1a;【Hot 100】94. 二叉樹的中序遍歷?? 寄語&#xff1a;書到用時方恨少&#xff…

大語言模型(LLMs)微調技術總結

文章目錄 全面總結當前大語言模型&#xff08;LLM&#xff09;微調技術1. 引言2. 為什么需要微調&#xff1f;3. 微調技術分類概覽4. 各種微調技術詳細介紹4.1 基礎微調方法4.1.1 有監督微調&#xff08;Supervised Fine-Tuning, SFT&#xff09;4.1.2 全參數微調&#xff08;F…

解決Maven項目中報錯“java不支持版本6即更高的版本 7”

錯誤背景 當Maven項目編譯或運行時出現錯誤提示 Java不支持版本6即更高的版本7&#xff0c;通常是由于項目配置的JDK版本與當前環境或編譯器設置不一致導致的。例如&#xff1a; 項目配置的Java版本為6或7&#xff0c;但實際使用的是JDK 17。Maven或IDE的編譯器未正確指定目標…

C++筆記-多態(包含虛函數,純虛函數和虛函數表等)

1.多態的概念 多態(polymorphism)的概念:通俗來說&#xff0c;就是多種形態。多態分為編譯時多態(靜態多態)和運行時多態(動態多態)&#xff0c;這里我們重點講運行時多態&#xff0c;編譯時多態(靜態多態)和運行時多態(動態多態)。編譯時多態(靜態多態)主要就是我們前面講的函…

【Unity】MVP框架的使用例子

在提到MVP之前&#xff0c;可以先看看這篇MVC的帖子&#xff1a; 【Unity】MVC的簡單分享以及一個在UI中使用的例子 MVC的不足之處&#xff1a; 在MVC的使用中&#xff0c;會發現View層直接調用了Model層的引用&#xff0c;即這兩個層之間存在著一定的耦合性&#xff0c;而MV…

前端js學算法-實踐

1、兩數之和 const twoSum (nums, target) > {const obj {}for (let m 0; m < nums.length; m) {const cur nums[m]const diff target - curif(obj.hasOwnProperty(diff)){ // 查詢對象中是否存在目標值-當前值鍵值對console.log([obj[diff], m]) // 存在則直接獲取…

《MATLAB實戰訓練營:從入門到工業級應用》趣味入門篇-用聲音合成玩音樂:MATLAB電子琴制作(超級趣味實踐版)

《MATLAB實戰訓練營&#xff1a;從入門到工業級應用》趣味入門篇-用聲音合成玩音樂&#xff1a;MATLAB電子琴制作&#xff08;超級趣味實踐版&#xff09; 開篇&#xff1a;當MATLAB遇見音樂 - 一場數字與藝術的浪漫邂逅 想象一下&#xff0c;你正坐在一臺古老的鋼琴前&#x…

實戰探討:為什么 Redis Zset 選擇跳表?

在了解了跳表的原理和實現后&#xff0c;一個常見的問題&#xff08;尤其是在面試中&#xff09;隨之而來&#xff1a;為什么像 Redis 的有序集合 (Zset) 這樣的高性能組件會選擇使用跳表&#xff0c;而不是大家熟知的平衡樹&#xff08;如紅黑樹&#xff09;呢&#xff1f; 對…

數據結構-線性結構(鏈表、棧、隊列)實現

公共頭文件common.h #define TRUE 1 #define FALSE 0// 定義節點數據類型 #define DATA_TYPE int單鏈表C語言實現 SingleList.h #pragma once#include "common.h"typedef struct Node {DATA_TYPE data;struct Node *next; } Node;Node *initList();void headInser…

高中數學聯賽模擬試題精選學數學系列第3套幾何題

△ A B C \triangle ABC △ABC 的內切圓 ⊙ I \odot I ⊙I 分別與邊 B C BC BC, C A CA CA, A B AB AB 相切于點 D D D, E E E, F F F, D D ′ DD DD′ 為 ⊙ I \odot I ⊙I 的直徑, 過圓心 I I I 作直線 A D ′ AD AD′ 的垂線 l l l, 直線 l l l 分別與 D E DE…

使用 ossutil 上傳文件到阿里云 OSS

在處理文件存儲和傳輸時&#xff0c;阿里云的對象存儲服務&#xff08;OSS&#xff09;是一個非常方便的選擇。特別是在需要批量上傳文件或通過命令行工具進行文件管理時&#xff0c;ossutil提供了強大的功能。本文將詳細說明如何使用 ossutil 上傳文件到阿里云 OSS&#xff0c…

DeepSeek與MySQL:開啟數據智能新時代

目錄 一、引言&#xff1a;技術融合的力量二、DeepSeek 與 MySQL&#xff1a;技術基石2.1 DeepSeek 技術探秘2.2 MySQL 數據庫深度解析 三、DeepSeek 與 MySQL 集成&#xff1a;從理論到實踐3.1 集成原理剖析3.2 集成步驟詳解 四、應用案例&#xff1a;實戰中的價值體現4.1 電商…

WebAPI項目從Newtonsoft.Json遷移到System.Text.Json踩坑備忘

1.控制器層方法返回類型不能為元組 控制器層方法返回類型為元組時&#xff0c;序列化結果為空。 因為元組沒有屬性只有field&#xff0c;除非使用IncludeFields參數專門指定&#xff0c;否則使用System.Text.Json進行序列化時不會序列化field var options new JsonSerializ…