如何用Python实现飞机大战小游戏

飞机大战是个什么样的小游戏呢?

  • 首先我们需要有一个自己的飞机,它可以在画面上进行上下左右移动,我们通过方向键来控制它的移动,我们的飞机要发射子弹,用来击打敌机,我们用空格键来控制子弹的发射

  • 然后需要设置敌机,随机出现在画面上,以一定的速度向下移动 敌机和我们自己的飞机相撞时游戏结束

  • 游戏结束时统计得分,击落一只敌机得10分

    至此,我们一个飞机大战的小游戏就设计完成了!那么,要如何实现呢?

上完整代码:

python 复制代码
# air_shoot.py
# 飞机大战小游戏

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)

# 时钟(控制帧率)
clock = pygame.time.Clock()

# 字体
font = pygame.font.SysFont("simhei", 32)  # 如果报错,改为 None 或 "Arial"
small_font = pygame.font.SysFont("simhei", 24)

# 玩家飞机
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)

# 敌机
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)

# 游戏结束画面
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()

# 主游戏函数
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  # 帧数(越小越密集)
    running = True

    while running:
        clock.tick(60)
        current_frame = pygame.time.get_ticks() // 1000 * 60  # 当前帧数(粗略)

        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        # 按键射击(长按连续发射)
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            if len(bullets) < 5:  # 限制子弹数量
                player.shoot()

        # 生成敌机
        if random.randint(1, enemy_spawn_rate) == 1:
            enemy = Enemy()
            all_sprites.add(enemy)
            enemies.add(enemy)

        # 更新所有精灵
        all_sprites.update()

        # 子弹击中敌机
        hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
        for hit in hits:
            score += 10

        # 玩家与敌机碰撞
        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()

    # 游戏结束
    show_game_over(score)

# 主循环(支持重玩)
while True:
    game()

🛩️ 游戏整体结构

这个游戏使用了 Pygame 框架面向对象编程(OOP) 的方式来组织代码。主要分为以下几个部分:

  1. 初始化设置
  2. 定义游戏对象类(玩家、敌机、子弹)
  3. 游戏主循环
  4. 碰撞检测与得分
  5. 游戏结束界面
  6. 支持重玩机制

✅ 第一部分:导入模块和初始化

python 复制代码
import pygame
import random
import sys
  • pygame:核心游戏库。
  • random:用于生成随机位置、速度等。
  • sys:用于安全退出程序。
python 复制代码
pygame.init()

初始化所有 Pygame 的模块(如声音、显示、字体等),这是使用 Pygame 的第一步。

python 复制代码
WIDTH, HEIGHT = 480, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("飞机大战")
  • 设置窗口大小为 480×600 像素。
  • 创建一个显示窗口,并设置标题为"飞机大战"。
python 复制代码
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) 是红色(敌机)
  • (0, 255, 0) 是绿色(玩家)
python 复制代码
clock = pygame.time.Clock()

创建一个时钟对象,用来控制游戏帧率(FPS),防止运行过快或过慢。

python 复制代码
font = pygame.font.SysFont("simhei", 32)
small_font = pygame.font.SysFont("simhei", 24)

创建字体对象,用于在屏幕上绘制文字。

  • "simhei" 是黑体,支持中文。
  • 如果系统没有这个字体,可以用 'Arial'None 替代。

✅ 第二部分:定义游戏角色类

🎮 1. 玩家飞机类 Player
python 复制代码
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 中所有可移动对象的基础类。
  • image:角色的外观,这里是一个绿色矩形(50宽 × 40高)。
  • rect:角色的位置和边界框。
  • 初始位置:水平居中,底部距离屏幕底边 10 像素。
  • speed:移动速度。
python 复制代码
    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

每一帧调用一次 update() 方法:

  • 获取当前按下的按键状态。
  • 控制方向键移动。
  • 加入边界判断,不让飞机飞出窗口。
python 复制代码
    def shoot(self):
        bullet = Bullet(self.rect.centerx, self.rect.top)
        all_sprites.add(bullet)
        bullets.add(bullet)

发射子弹的方法:

  • 在飞机顶部中心创建一颗子弹。
  • 把它加入总精灵组 all_sprites 和子弹组 bullets,以便更新和绘制。

👾 2. 敌机类 Enemy
python 复制代码
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)
  • 红色矩形代表敌机。
  • 出现在屏幕上方(y 为负值),从不同 x 位置随机出现。
  • 下落速度随机(2~5像素/帧)。
python 复制代码
    def update(self):
        self.rect.y += self.speed
        if self.rect.top > HEIGHT:
            self.kill()  # 移出屏幕后删除

敌机持续下落,一旦完全移出屏幕底部就自动销毁(kill()),避免内存泄漏。


🔫 3. 子弹类 Bullet
python 复制代码
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  # 负数表示向上飞
  • 白色小矩形表示子弹。
  • 从玩家飞机顶部发射。
  • 向上飞行(speed = -10)。
python 复制代码
    def update(self):
        self.rect.y += self.speed
        if self.rect.bottom < 0:
            self.kill()  # 子弹飞出屏幕顶端就销毁

✅ 第三部分:辅助函数

🖋️ 显示文字函数
python 复制代码
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)

封装了一个通用的文字绘制函数:

  • surf:要画在哪(通常是 screen
  • text:要显示的文字
  • font:字体对象
  • (x, y):文字左上角坐标
  • blit():把文字图像画到屏幕上

💀 游戏结束画面
python 复制代码
def show_game_over(score):
    screen.fill(BLACK)
    draw_text(screen, "游戏结束", font, WIDTH//2, HEIGHT//2 - 50, RED)
    draw_text(screen, f"得分: {score}", small_font, WIDTH//2, HEIGHT//2)
    draw_text(screen, "按 R 重新开始,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()

显示"游戏结束"界面并等待用户选择:

  • 填黑背景,显示得分。
  • 提示按 R 重玩,Q 退出。
  • 使用一个循环等待输入,直到用户决定。

✅ 第四部分:主游戏函数 game()

python 复制代码
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帧左右生成一架敌机
    running = True

初始化游戏状态:

  • 创建三个精灵组:
    • all_sprites:所有要绘制和更新的对象
    • bullets:所有子弹
    • enemies:所有敌机
  • 添加玩家
  • 得分从 0 开始
python 复制代码
    while running:
        clock.tick(60)  # 锁定60 FPS

        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

主循环每秒运行约 60 次(由 clock.tick(60) 控制)。

处理退出事件。

python 复制代码
        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            if len(bullets) < 5:  # 限制最多5发子弹
                player.shoot()

检测是否按下空格键,如果是且子弹不多于5个,则发射。

python 复制代码
        # 生成敌机
        if random.randint(1, enemy_spawn_rate) == 1:
            enemy = Enemy()
            all_sprites.add(enemy)
            enemies.add(enemy)

随机生成敌机(大约每 30 帧生成一架)。

python 复制代码
        all_sprites.update()

更新所有精灵的位置(包括玩家、敌机、子弹)。

python 复制代码
        # 子弹击中敌机
        hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
        for hit in hits:
            score += 10

groupcollide() 自动检测两组精灵之间的碰撞:

  • 子弹打中敌机 → 双方都销毁(True, True
  • 每消灭一个敌机加 10 分
python 复制代码
        # 玩家与敌机碰撞
        if pygame.sprite.spritecollide(player, enemies, False):
            running = False

如果玩家碰到任何敌机(即使只是擦边),游戏结束。

python 复制代码
        # 绘制画面
        screen.fill(BLACK)
        all_sprites.draw(screen)
        draw_text(screen, f"得分: {score}", small_font, 60, 10)
        pygame.display.flip()

清屏 → 画所有精灵 → 显示得分 → 刷新屏幕

python 复制代码
    show_game_over(score)  # 游戏结束后显示结束画面

✅ 第五部分:支持重复游戏

python 复制代码
while True:
    game()

主循环外再套一层 while True,这样每次游戏结束后都可以重新开始。


🧠 总结:游戏运行流程图

复制代码
开始游戏
   ↓
初始化 Pygame 和变量
   ↓
进入 game() 函数
   ↓
创建玩家和精灵组
   ↓
主循环:
   → 处理事件(退出、按键)
   → 玩家移动/射击
   → 随机生成敌机
   → 更新所有精灵位置
   → 检测碰撞(子弹打敌机、玩家撞敌机)
   → 绘制画面和得分
   ↓
玩家被撞 → 结束主循环
   ↓
调用 show_game_over()
   ↓
等待用户按 R 或 Q
   → 按 R:回到 game() 重新开始
   → 按 Q:退出程序

🚀 后续扩展建议

你可以基于这个框架继续添加功能:

功能 实现思路
添加音效 使用 pygame.mixer.Sound() 播放射击、爆炸音效
使用图片代替方块 pygame.image.load("player.png")
添加爆炸动画 碰撞时播放一系列图片
生命值系统 玩家可承受多次撞击
道具掉落 敌机死亡时随机掉落加速、多子弹等道具
相关推荐
AI科技星33 分钟前
为什么宇宙无限大?
开发语言·数据结构·经验分享·线性代数·算法
杨超越luckly38 分钟前
基于 Overpass API 的城市电网基础设施与 POI 提取与可视化
python·数据可视化·openstreetmap·电力数据·overpass api
Appreciate(欣赏)1 小时前
JAVA使用poi类读取xlxs文件内容拼接成添加数据SQL
java·开发语言·sql
oioihoii1 小时前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
开发语言·c++
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于JAVA的恒星酒店客房管理系统为例,包含答辩的问题和答案
java·开发语言
思密吗喽1 小时前
景区行李寄存管理系统
java·开发语言·spring boot·毕业设计·课程设计
Rust语言中文社区1 小时前
【Rust日报】Dioxus 用起来有趣吗?
开发语言·后端·rust
小灰灰搞电子1 小时前
Rust Slint实现颜色选择器源码分享
开发语言·后端·rust
q***23572 小时前
python的sql解析库-sqlparse
数据库·python·sql
18你磊哥2 小时前
Django WEB 简单项目创建与结构讲解
前端·python·django·sqlite