像素飞机大战(含Python源码)

前言

有了前面的基础想对“外星人入侵”这游戏进行修改,去除导入图片的部分,直接使用pygame来实现,再增加一些特色的功能来让游戏更加多样。

使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147686449?spm=1001.2014.3001.5501贪吃蛇(含Python源码)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147660127?spm=1001.2014.3001.5501外星人入侵(python)_外星人入侵python源代码-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/135963588?spm=1001.2014.3001.5501

原始代码

使用DeepSeek生成的代码如下:

import pygame
import random

# 初始化 Pygame
pygame.init()

# 游戏窗口设置
WIDTH = 480
HEIGHT = 600
FPS = 60

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)

# 初始化窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("像素飞机大战")
clock = pygame.time.Clock()

# 玩家飞机参数
PLAYER_WIDTH = 40
PLAYER_HEIGHT = 30

# 子弹参数
BULLET_SIZE = 6

# 敌机参数
ENEMY_SIZES = [(30, 25), (35, 30), (40, 35)]

# 爆炸粒子参数
EXPLOSION_PARTICLES = 20


# 玩家类
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((PLAYER_WIDTH, PLAYER_HEIGHT))
        self.image.set_colorkey(BLACK)
        # 绘制三角形飞机
        pygame.draw.polygon(self.image, GREEN, [
            (0, PLAYER_HEIGHT),
            (PLAYER_WIDTH / 2, 0),
            (PLAYER_WIDTH, PLAYER_HEIGHT)
        ])
        self.rect = self.image.get_rect()
        self.rect.centerx = WIDTH // 2
        self.rect.bottom = HEIGHT - 20
        self.speedx = 8
        self.shoot_delay = 250
        self.last_shot = pygame.time.get_ticks()

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= self.speedx
        if keys[pygame.K_RIGHT]:
            self.rect.x += self.speedx
        self.rect.clamp_ip(screen.get_rect())

        if keys[pygame.K_SPACE]:
            self.shoot()

    def shoot(self):
        now = pygame.time.get_ticks()
        if now - self.last_shot > self.shoot_delay:
            self.last_shot = now
            bullet = Bullet(self.rect.centerx, self.rect.top)
            all_sprites.add(bullet)
            bullets.add(bullet)


# 子弹类
class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((BULLET_SIZE, BULLET_SIZE * 2))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y
        self.speedy = -10

    def update(self):
        self.rect.y += self.speedy
        if self.rect.bottom < 0:
            self.kill()


# 敌人类
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        size = random.choice(ENEMY_SIZES)
        self.image = pygame.Surface(size)
        self.image.fill(RED)
        # 添加敌机装饰
        pygame.draw.rect(self.image, ORANGE, (0, 0, size[0], 3))  # 顶部装饰条
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(WIDTH - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(2, 6)
        self.speedx = random.randrange(-3, 3)

    def update(self):
        self.rect.x += self.speedx
        self.rect.y += self.speedy
        if self.rect.top > HEIGHT + 10:
            self.kill()


# 爆炸效果类
class Explosion(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.particles = []
        # 生成爆炸粒子
        for _ in range(EXPLOSION_PARTICLES):
            self.particles.append([
                list(center),  # 位置
                [random.uniform(-3, 3), random.uniform(-5, 0)],  # 速度
                random.randint(4, 8)  # 半径
            ])
        self.image = pygame.Surface((1, 1))  # 虚拟表面
        self.rect = self.image.get_rect(center=center)
        self.frame = 0

    def update(self):
        self.frame += 1
        if self.frame > 30:  # 爆炸持续时间
            self.kill()

    def draw(self, surf):
        for particle in self.particles:
            pos, vel, radius = particle
            # 更新粒子位置
            pos[0] += vel[0]
            pos[1] += vel[1]
            # 绘制渐变效果
            color = (random.randint(200, 255), random.randint(50, 150), 0)
            pygame.draw.circle(surf, color, (int(pos[0]), int(pos[1])), radius)


# 创建精灵组
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
explosions = pygame.sprite.Group()

player = Player()
all_sprites.add(player)


# 生成初始敌机
def spawn_enemy():
    enemy = Enemy()
    all_sprites.add(enemy)
    enemies.add(enemy)


for _ in range(8):
    spawn_enemy()

# 游戏循环
running = True
score = 0
enemy_spawn_timer = 0

# 字体设置
font = pygame.font.Font(None, 36)

while running:
    clock.tick(FPS)

    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 生成新敌机
    enemy_spawn_timer += 1
    if enemy_spawn_timer > 45:
        spawn_enemy()
        enemy_spawn_timer = 0

    # 更新
    all_sprites.update()

    # 子弹与敌机碰撞检测
    hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
    for hit in hits:
        score += 50
        explosion = Explosion(hit.rect.center)
        all_sprites.add(explosion)
        explosions.add(explosion)

    # 玩家与敌机碰撞检测
    if pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_rect_ratio(0.8)):
        running = False

    # 绘制
    screen.fill(BLACK)

    # 绘制所有精灵
    all_sprites.draw(screen)

    # 绘制爆炸效果
    for explosion in explosions:
        explosion.draw(screen)

    # 绘制分数
    score_text = font.render(f"Score: {score}", True, WHITE)
    screen.blit(score_text, (10, 10))

    pygame.display.flip()

pygame.quit()

优化

实在是改不动了,就这样吧,原本想优化敌机,增加射击功能或者增加敌机的形状和动态装饰,他也确实增加了,但是一直没生效,然后目前还存在很多重复的代码也没有删除。

可以通过调整道具掉落的概率来设置游戏的难度:

# 新增道具掉落(80%概率)
if random.random() < 0.8:
    powerup = PowerUp(hit.rect.center)
    all_sprites.add(powerup)
    powerups.add(powerup)

后续还可以增加道具的种类和功能。

多样化道具系统 [PowerUp类]:

护盾机制

  • 金色护盾持续10秒,碰撞敌机免伤
  • 动态护盾动画(多层同心圆脉冲效果)

火力增强

  • 双倍射速(火力提升100%持续10秒)
  • 三向散射(5秒内发射三方向蓝色子弹)

特殊效果

  • 子弹弹射(青色子弹可边界反弹3次)
  • 敌机减速(全体敌机移速降低50%持续5秒)
  • 狂暴模式(射速提升60%持续5秒)
  • 方向混乱(左右移动方向反转持续5秒)
  • 黑洞(吸引屏幕上的所有道具和敌机持续7秒)

  • 护盾机制:玩家飞机颜色变为金色表示护盾激活状态。
  • 双倍射速:通过pygame.time.set_timer(pygame.USEREVENT + 1, 0)清除旧计时器,并设置新计时器(10000毫秒)来控制持续时间。
  • 三向散射:立即触发一次三向射击,左中右三个方向发射子弹。
  • 子弹弹射:在边界处反弹最多3次,每次反弹会生成火花粒子特效。
  • 敌机减速:所有敌机速度减半,并且颜色变为紫色,结束时恢复原始颜色。
  • 狂暴模式:射速显著提升,适合需要快速输出的场景。
  • 方向混乱:左右移动方向反转,影响玩家操作体验。
  • 黑洞:产生吸引力,吸引屏幕上的所有道具和敌机,并带有屏幕扭曲和震动效果。
  • 生命值:直接增加1点生命值,无持续时间限制。

动态敌机行为 [Enemy类](未实现)

形态多样性

  • 4种基础形状(圆形/三角形/六边形/矩形)
  • 30%概率附加装饰部件(机翼/炮塔/装甲等)

智能机动

  • 正弦波规避轨迹(带随机扰动因子)
  • 尺寸差异化行为(小敌机高机动/大敌机稳路径)

状态反馈

  • 被减速时变紫色+移动路径紊乱
  • 受击时颜色渐变(彩虹效果)

进阶战斗机制

合射击系统 [Bullet类]

  • 基础黄色子弹 / 双倍橙色子弹 / 弹射青色子弹
  • 三向蓝色散射弹道(角度:-30°, 0°, 30°)

物理模拟

  • 子弹水平速度变量(speedx实现抛物线)
  • 弹射次数限制(最多3次边界反弹)

沉浸式视觉体验

动态背景

  • 150颗流星/星星构成星空(2%流星概率)
  • 流星拖尾效果(10段渐隐轨迹线)

粒子特效

  • 爆炸火花(20个随机运动粒子)
  • 护盾多层光晕(透明度波动效果)

状态指示

  • 机身颜色变化(正常蓝↔护盾金)
  • 尾部喷射火焰(橙黄交替闪烁)

 
策略生存设计

资源管理

  • 3条生命值显示(绿色计数器)
  • 道具冷却提示(屏幕下方闪烁文字)

难度曲线

  • 敌机45帧/次生成频率
  • 大中小敌机差异速度(比例因子:1.5/1.2/1.0)

永久成长

  • 本地高分存档(highscore.txt)
  • 得分倍率机制(击毁敌机+50分)

 代码

import random
from typing import TypeVar
import pygame
import math

TSprite = TypeVar('TSprite', bound=pygame.sprite.Sprite)

# 高分文件路径
HIGHSCORE_FILE = "highscore.txt"


def read_high_score():
    try:
        with open(HIGHSCORE_FILE, 'r') as f:
            return int(f.read())
    except (IOError, ValueError):
        return 0


def write_high_score(score):
    with open(HIGHSCORE_FILE, 'w') as f:
        f.write(str(score))


# 初始化 Pygame
pygame.init()

# 游戏窗口设置
WIDTH = 480
HEIGHT = 600
FPS = 60

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
SHIP_BODY_COLOR = (30, 144, 255)
THRUSTER_COLOR = (255, 215, 0)
OVERLAY_COLOR = (0, 0, 0, 160)
# 在颜色定义区域添加星空颜色(约第38行)
STAR_COLOR = (200, 200, 200)  # 浅灰色
CYAN = (0, 255, 255)  # 青色
PINK = (255, 0, 127)  # 狂暴道具颜色
PURPLE = (128, 0, 128)  # 紫色
DARK_GRAY = (64, 64, 64)  # 深灰色
DARK_RED = (139, 0, 0)  # 深红色
CONFUSION_BLUE = (25, 25, 112)  # 深蓝色
CONFUSION_PURPLE = (148, 0, 211)  # 紫色
BLACK_HOLE_COLOR = (169, 169, 169)  # 灰色

# 初始化窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("像素飞机大战")
clock = pygame.time.Clock()
# 新增字体路径 ↓
font_path = "C:/Windows/Fonts/simhei.ttf"

# 玩家飞机参数
PLAYER_WIDTH = 40
PLAYER_HEIGHT = 30

# 子弹参数
BULLET_SIZE = 6

# 敌机参数
ENEMY_SIZES = [(30, 25), (35, 30), (40, 35)]
# 形状模板库(单位坐标)
SHAPE_TEMPLATES = [
    [(-15, 0), (0, 10), (15, 0), (0, -10)],  # 原始菱形
    [(-20, 5), (0, 15), (20, 5), (10, -5), (-10, -5)],  # 五边形
    [(-12, -8), (12, -8), (0, 12)]  # 三角形
]
# 在SHAPE_TEMPLATES下方添加新模板
SHAPE_TEMPLATES += [
    # 六边形
    [(-12, 0), (-6, -10), (6, -10), (12, 0), (6, 10), (-6, 10)],
    # 星形
    [(0, -15), (5, -5), (15, 0), (5, 5), (10, 15),
     (0, 10), (-10, 15), (-5, 5), (-15, 0), (-5, -5)],
    # 不对称锯齿形
    [(-15, 0), (-10, 10), (0, 5), (10, 15), (15, 0), (5, -10)]
]

# 修改后的SHAPE_CACHE定义(添加缺失的形状)
SHAPE_CACHE = {
    # 圆形(使用多边形近似)
    'circle': [(0.5 + 0.5 * math.cos(math.radians(ang)),
                0.5 + 0.5 * math.sin(math.radians(ang)))
               for ang in range(0, 360, 30)],
    # 三角形
    'triangle': [(0.5, 0), (1, 1), (0, 1)],
    # 六边形
    'hexagon': [(0.5 + 0.5 * math.cos(math.radians(60 * i - 30)),
                 0.5 + 0.5 * math.sin(math.radians(60 * i - 30)))
                for i in range(6)],
    # 矩形
    'rectangle': [(0, 0), (1, 0), (1, 1), (0, 1)],
    # 删除冗余的arrow和diamond定义(已在SHAPE_TEMPLATES中存在)
}
# 爆炸粒子参数
EXPLOSION_PARTICLES = 20


# 道具类
class PowerUp(pygame.sprite.Sprite):
    TYPES = ['shield', 'double', 'life', 'ricochet', 'rage', 'slow', 'triple', 'confusion', 'blackhole']

    def __init__(self, center):
        super().__init__()
        self.type = random.choice(self.TYPES)
        colors = {'shield': (255, 215, 0), 'double': ORANGE, 'life': GREEN, 'ricochet': CYAN, 'rage': PINK,
                  'slow': PURPLE, 'triple': (0, 255, 255), 'confusion': CONFUSION_PURPLE, 'blackhole': BLACK_HOLE_COLOR}

        # 创建不同形状的道具
        self.image = pygame.Surface((20, 20), pygame.SRCALPHA)
        if self.type == 'shield':
            # pygame.draw.circle(self.image, colors[self.type], (10, 10), 8, 2)
            # 六芒星
            outer_points = [(10, 2), (13, 6), (18, 6), (14, 10),
                            (18, 14), (13, 14), (10, 18),
                            (7, 14), (2, 14), (6, 10),
                            (2, 6), (7, 6)]
            pygame.draw.polygon(self.image, colors[self.type], outer_points, 2)
        elif self.type == 'double':
            pygame.draw.rect(self.image, colors[self.type], (5, 5, 10, 10))
        elif self.type == 'life':
            # pygame.draw.polygon(self.image, colors[self.type],
            #                     [(10, 2), (18, 18), (2, 18)])
            # 绘制无限符号
            pygame.draw.arc(self.image, (32, 178, 170), (2, 2, 16, 16),
                            math.pi / 4, 3 * math.pi / 4, 2)
            pygame.draw.arc(self.image, (32, 178, 170), (2, 2, 16, 16),
                            -3 * math.pi / 4, -math.pi / 4, 2)
            # 中心点
            pygame.draw.circle(self.image, colors[self.type], (10, 10), 2)
        elif self.type == 'ricochet':  # 菱形
            pygame.draw.polygon(self.image, CYAN, [
                (5, 10), (10, 5), (15, 10), (10, 15)
            ])
        elif self.type == 'rage':
            # 闪电形状坐标点
            points = [(5, 5), (12, 5), (8, 10), (15, 10), (5, 15)]
            pygame.draw.lines(self.image, colors[self.type], False, points, 3)
        elif self.type == 'slow':
            # 沙漏形状
            pygame.draw.polygon(self.image, colors[self.type],
                                [(5, 5), (15, 5), (10, 10), (5, 15), (15, 15)])
            pygame.draw.line(self.image, colors[self.type], (10, 10), (10, 15), 2)
        elif self.type == 'triple':
            # 绘制三个箭头表示三向
            for offset in [-6, 0, 6]:
                pygame.draw.polygon(self.image, colors[self.type], [
                    (10 + offset, 5), (13 + offset, 9), (10 + offset, 13)
                ])
        elif self.type == 'confusion':
            # 绘制螺旋线
            for i in range(3, 0, -1):
                rect = pygame.Rect(2 * i, 2 * i, 24 - 4 * i, 24 - 4 * i)
                pygame.draw.arc(self.image, colors[self.type], rect, 0, math.pi * 2, 2)
            # 添加中心箭头
            pygame.draw.polygon(self.image, WHITE, [(12, 6), (9, 12), (15, 12)])
        elif self.type == 'blackhole':
            self.image = pygame.Surface((32, 32), pygame.SRCALPHA)  # 增大尺寸
            # 动态扭曲效果
            angle = pygame.time.get_ticks() / 20 % 360

            # 绘制多层旋转结构
            for i in range(6):  # 六层动态结构
                radius = 14 - i * 2
                points = [
                    (16 + radius * math.cos(math.radians(angle + j * 60)),
                     16 + radius * math.sin(math.radians(angle + j * 60)))
                    for j in range(6)
                ]
                color = (50 + i * 20, 50 + i * 20, 50 + i * 20, 200)
                pygame.draw.polygon(self.image, color, points, 2)

            # 添加核心脉冲
            core_size = 4 + 2 * math.sin(pygame.time.get_ticks() / 100)
            pygame.draw.circle(self.image, (200, 200, 200), (16, 16), int(core_size))

            # 添加引力扭曲线(更粗更密集)
            for i in range(0, 360, 20):  # 更密集的角度
                rad = math.radians(i + angle)
                length = 10 + 5 * math.sin(pygame.time.get_ticks() / 50)
                end_x = 16 + length * math.cos(rad)
                end_y = 16 + length * math.sin(rad)
                pygame.draw.line(self.image, (100, 100, 100), (16, 16), (end_x, end_y), 2)

        self.rect = self.image.get_rect(center=center)
        self.speedy = 2  # 下落速度

    def update(self):
        self.rect.y += self.speedy
        if self.rect.top > HEIGHT:
            self.kill()


# 在游戏状态区域添加星空初始化
class Star:
    def __init__(self):
        self.reset()  # 添加这行初始化属性
        self.is_meteor = random.random() < 0.02  # 2%概率是流星
        if self.is_meteor:
            self.tail = []

    def update(self):  # 需要实际更新流星位置
        if self.is_meteor:
            self.x += random.uniform(-0.5, 0.5)  # 流星随机左右飘动
            self.y += self.speed * 2  # 流星下落更快
            if len(self.tail) < 10:
                self.tail.insert(0, (self.x, self.y))
            else:
                self.tail.pop()
        else:
            self.y += self.speed  # 普通星星正常下落

        if self.y > HEIGHT + 10:
            self.reset()

    def reset(self):
        self.x = random.randint(0, WIDTH)
        self.y = random.randint(-HEIGHT, 0)  # 初始位置在屏幕上方之外
        self.speed = random.uniform(0.5, 2.5)
        self.size = random.randint(1, 2)


stars = [Star() for _ in range(150)]  # 创建150颗星星


#  在游戏状态区域添加星空
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((PLAYER_WIDTH, PLAYER_HEIGHT))
        self.image.set_colorkey(BLACK)
        self.normal_color = (30, 144, 255)  # 原蓝色
        self.shield_color = (255, 215, 0)  # 金色
        pygame.draw.line(self.image, YELLOW,
                         (PLAYER_WIDTH // 2 - 3, PLAYER_HEIGHT - 5),
                         (PLAYER_WIDTH // 2 + 3, PLAYER_HEIGHT - 5), 4)
        self.rect = self.image.get_rect(centerx=WIDTH // 2, bottom=HEIGHT - 20)
        self.speedx = 8
        self.shoot_delay = 250
        self.last_shot = pygame.time.get_ticks()
        self.shield = False
        self.shield_time = 0
        self.double_fire = False
        self.lives = 3  # 添加生命值系统
        self.powerup_text = ""
        self.text_timer = 0
        self.ricochet_active = False
        self.ricochet_time = 0
        self.rage_active = False  # 新增狂暴状态
        self.original_shoot_delay = 250  # 保存原始射速
        # 新增类属性保存坐标点
        self.cockpit_points = [
            (PLAYER_WIDTH // 2 - 8, 0),
            (PLAYER_WIDTH // 2 + 8, 0),
            (PLAYER_WIDTH // 2 + 4, PLAYER_HEIGHT // 3),
            (PLAYER_WIDTH // 2 - 4, PLAYER_HEIGHT // 3)
        ]
        # 原绘制代码改为使用属性 ↓
        pygame.draw.polygon(self.image, self.normal_color, self.cockpit_points)
        self.triple_fire = False
        self.triple_duration = 0  # 持续时间(毫秒)
        self.triple_start_time = 0  # 新增启动时间记录
        # 添加混乱状态属性
        self.confused = False
        self.confuse_start = 0
        self.confuse_duration = 5000  # 5秒
        self.blackhole_active = False  # 新增黑洞状态
        self.blackhole_start_time = 0
        self.blackhole_duration = 7000  # 持续7秒

    def triple_shot(self):
        angles = [-30, 0, 30]  # 左中右三个方向

        for angle in angles:
            rad = math.radians(angle)
            # 计算速度分量(保持总速度与普通子弹一致)
            speed_magnitude = 10
            speedx = math.sin(rad) * speed_magnitude
            speedy = math.cos(rad) * -speed_magnitude
            bullet = Bullet(
                self.rect.centerx,
                self.rect.top,
                speedx=speedx,
                speedy=speedy,  # 这个参数的存在将触发颜色判断
                ricochet=False
            )
            bullet.image.fill(BLUE)  # 青色子弹
            all_sprites.add(bullet)
            bullets.add(bullet)

    # 新增方法:应用黑洞扭曲效果
    def apply_blackhole_distortion(self):
        # 创建扭曲表面
        distortion_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)

        time_factor = pygame.time.get_ticks() / 100

        for x in range(0, WIDTH, 20):
            for y in range(0, HEIGHT, 20):
                dx = x - self.rect.centerx
                dy = y - self.rect.centery
                dist = math.hypot(dx, dy)

                if dist < 600:
                    strength = (1 - dist / 600) * 15
                    angle = time_factor + math.atan2(dy, dx)
                    offset_x = math.cos(angle) * strength
                    offset_y = math.sin(angle) * strength

                    if random.random() < 0.2:
                        pygame.draw.circle(distortion_surface,
                                           (255, 255, 255, int(150 * (1 - dist / 600))),
                                           (int(x + offset_x), int(y + offset_y)),
                                           random.randint(1, 3))

        # 径向模糊
        blur_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        for i in range(30):
            angle = random.uniform(0, 2 * math.pi)
            length = random.uniform(100, 300)
            start_pos = (self.rect.centerx + math.cos(angle) * length,
                         self.rect.centery + math.sin(angle) * length)
            end_pos = (self.rect.centerx, self.rect.centery)
            pygame.draw.line(blur_surface, (200, 200, 200, 60), start_pos, end_pos, random.randint(1, 2))

        # 屏幕震动(修复后)
        shake_intensity = int(2 * math.sin(time_factor))
        x_shake = random.randint(min(-shake_intensity, shake_intensity), max(-shake_intensity, shake_intensity))
        y_shake = random.randint(min(-shake_intensity, shake_intensity), max(-shake_intensity, shake_intensity))

        screen.blit(screen, (x_shake, y_shake))

        # 组合所有效果
        screen.blit(distortion_surface, (0, 0))
        screen.blit(blur_surface, (0, 0))

    def update(self):
        keys = pygame.key.get_pressed()

        # 修改移动逻辑
        if self.confused:
            # 左右反转
            move_x = (keys[pygame.K_LEFT] - keys[pygame.K_RIGHT])
        else:
            move_x = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT])

        self.rect.x += move_x * self.speedx

        # 更新混乱状态
        if self.confused and pygame.time.get_ticks() - self.confuse_start > self.confuse_duration:
            self.confused = False
            self.powerup_text = "方向感恢复!"
            self.text_timer = pygame.time.get_ticks()

        # if keys[pygame.K_LEFT]: self.rect.x -= self.speedx
        # if keys[pygame.K_RIGHT]: self.rect.x += self.speedx

        self.rect.clamp_ip(screen.get_rect())  # 确保飞机不移出屏幕

        # 新增颜色同步 ↓
        self.update_plane_color()  # 确保每帧更新颜色

        if keys[pygame.K_SPACE]: self.shoot()
        # 修改尾部火焰颜色判断 ↓
        thrust_color = self.shield_color if self.shield else YELLOW
        flame_color = ORANGE if pygame.time.get_ticks() % 100 < 50 else thrust_color
        self.image.set_at((self.rect.width // 2, self.rect.height - 2), flame_color)

        if pygame.time.get_ticks() % 100 < 50:
            self.image.set_at((self.rect.width // 2, self.rect.height - 2), ORANGE)
        else:
            self.image.set_at((self.rect.width // 2, self.rect.height - 2), YELLOW)
        if self.blackhole_active:
            # 增加屏幕扭曲效果
            self.apply_blackhole_distortion()
            # 吸引屏幕上的所有道具和敌机
            for sprite in all_sprites:
                if isinstance(sprite, (PowerUp, Enemy)):
                    dx = self.rect.centerx - sprite.rect.centerx
                    dy = self.rect.centery - sprite.rect.centery
                    dist = math.hypot(dx, dy)

                    if dist > 0 and dist < 1000:  # 仅当距离小于1000时产生吸引力
                        # 计算吸引方向
                        dx = dx / dist
                        dy = dy / dist

                        # 根据距离计算吸引力强度
                        strength = max(0.1, 3 * (1 - dist / 200))

                        # 应用吸引力
                        sprite.rect.x += dx * strength
                        sprite.rect.y += dy * strength
                        # 添加旋转力(每秒90度)
                        angle = math.radians(90 * (pygame.time.get_ticks() % 1000) / 1000)
                        sprite.rect.x += math.cos(angle) * 2
                        sprite.rect.y += math.sin(angle) * 2

    # 玩家射击
    def shoot(self):
        base_delay = self.original_shoot_delay
        # 如果处于狂暴状态则使用更快射速
        current_delay = self.shoot_delay if self.rage_active else base_delay
        now = pygame.time.get_ticks()
        if now - self.last_shot > current_delay:
            self.last_shot = now

            # 三向射击模式
            if self.triple_fire:
                # print('三向射击模式被调用')
                self.triple_shot()

            offset = 15 if self.double_fire else 0
            # 新增弹射状态判断
            bullet_props = {
                'is_double': self.double_fire,
                'ricochet': self.ricochet_active,
                'speedx': random.choice([-3, 3]) if self.ricochet_active else 0
            }
            # 双倍火力时发射两发子弹
            bullets_to_add = [
                Bullet(self.rect.centerx - offset, self.rect.top, **bullet_props),
                Bullet(self.rect.centerx + offset, self.rect.top, **bullet_props)
            ] if self.double_fire else [
                Bullet(self.rect.centerx, self.rect.top, **bullet_props)
            ]
            #  弹射时填充弹射颜色
            for bullet in bullets_to_add:
                if bullet.ricochet:
                    bullet.image.fill(CYAN)
                    # 添加对角白线
                    pygame.draw.line(bullet.image, WHITE,
                                     (0, 0), (BULLET_SIZE, BULLET_SIZE * 2), 2)
                all_sprites.add(bullet)
                bullets.add(bullet)

    def draw_shield(self):
        if self.shield:
            radius = max(self.rect.width, self.rect.height) + 10
            shield_surf = pygame.Surface((radius * 2, radius * 2), pygame.SRCALPHA)

            # 使用护盾颜色中的金色
            alpha = int(200 + 50 * math.sin(pygame.time.get_ticks() / 100))
            for i in range(3):  # 绘制三层同心圆
                pygame.draw.circle(shield_surf, (255, 215, 0, alpha // (i + 1)),
                                   (radius, radius), radius - i * 3, 3)

            screen.blit(shield_surf, (self.rect.centerx - radius,
                                      self.rect.centery - radius))

    def update_plane_color(self):
        """根据护盾状态更新飞机颜色"""
        current_color = self.shield_color if self.shield else self.normal_color
        # 重绘前保留火焰像素点 ↓
        flame_pixel = self.image.get_at((self.rect.width // 2, self.rect.height - 2))
        # 重绘飞机主体
        self.image.fill(BLACK)
        pygame.draw.rect(self.image, current_color, (5, 5, PLAYER_WIDTH - 10, PLAYER_HEIGHT - 15))
        pygame.draw.polygon(self.image, current_color, self.cockpit_points)
        # 恢复火焰像素 ↓
        self.image.set_at((self.rect.width // 2, self.rect.height - 2), flame_pixel)
        # 新增尾部火焰基色 ↓
        thrust_base = self.shield_color if self.shield else YELLOW
        pygame.draw.line(self.image, thrust_base,
                         (PLAYER_WIDTH // 2 - 3, PLAYER_HEIGHT - 5),
                         (PLAYER_WIDTH // 2 + 3, PLAYER_HEIGHT - 5), 4)
        """添加扭曲效果"""
        if self.confused:
            # 创建扭曲表面
            distortion = pygame.Surface((PLAYER_WIDTH, PLAYER_HEIGHT), pygame.SRCALPHA)
            # 绘制波纹线
            for i in range(5):
                y = i * 6 + (pygame.time.get_ticks() % 100) / 20
                pygame.draw.line(distortion, (255, 255, 255, 50),
                                 (0, y), (PLAYER_WIDTH, y + random.randint(-3, 3)), 2)
            self.image.blit(distortion, (0, 0))


class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, is_double=False, ricochet=False, speedx=0, speedy=None):
        super().__init__()
        self.image = pygame.Surface((BULLET_SIZE, BULLET_SIZE * 2))
        self.image.fill(ORANGE if is_double else YELLOW)  # 双倍子弹颜色不同
        # 优先判断三向子弹
        if speedy is not None:  # 三向子弹的特殊情况
            self.image.fill(BLUE)
        elif ricochet:
            self.image.fill(CYAN)
            pygame.draw.line(self.image, WHITE, (0, 0), (BULLET_SIZE, BULLET_SIZE * 2), 2)
        else:
            self.image.fill(ORANGE if is_double else YELLOW)
        if is_double:
            pygame.draw.line(self.image, WHITE, (0, 0), (BULLET_SIZE, 0), 2)
        self.rect = self.image.get_rect(centerx=x, bottom=y)
        self.speedy = -12 if is_double else -10  # 双倍子弹更快
        self.speedx = speedx  # 新增水平速度
        self.ricochet = ricochet  # 是否可弹射
        self.bounce_count = 0  # 弹射次数
        self.is_double = is_double  # 新增属性
        self.x = x
        self.y = y
        # 修改速度初始化逻辑
        if speedy is not None:  # 如果传入了speedy参数
            self.speedy = speedy
        else:  # 保持原有逻辑
            self.speedy = -12 if is_double else -10

    def update(self):
        self.rect.y += self.speedy
        self.rect.x += self.speedx

        # 边界弹射逻辑 ↓
        if self.ricochet and self.bounce_count < 3:  # 最多弹射3次
            if self.rect.left <= 0 or self.rect.right >= WIDTH:
                self.speedx *= -1  # 反转水平速度
                self.bounce_count += 1
                # 添加弹射特效
                spark = Explosion(self.rect.center)
                spark.particles = [[list(self.rect.center),
                                    [random.uniform(-2, 2), random.uniform(-2, 2)],
                                    2] for _ in range(5)]
                all_sprites.add(spark)

        if self.rect.bottom < 0:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.shape_scale = random.uniform(0.8, 1.2)  # 随机缩放比例
        size = random.choice(ENEMY_SIZES)
        self.shape_type = random.choice(['circle', 'triangle', 'hexagon', 'rectangle'])
        base_size = random.randint(20, 40)
        self.color = tuple(random.randint(100, 255) for _ in range(3))
        # 统一表面创建逻辑
        if self.shape_type == 'circle':
            self.radius = base_size // 2
            self.image = pygame.Surface((base_size, base_size), pygame.SRCALPHA)
        else:
            self.image = pygame.Surface((base_size, base_size), pygame.SRCALPHA)

        self.rect = self.image.get_rect()
        self._draw_shape()

        # 创建带透明通道的表面
        self.image = pygame.Surface((int(size[0] * self.shape_scale),
                                     int(size[1] * self.shape_scale)),
                                    pygame.SRCALPHA)  # 保留透明度通道
        # 获取基础形状坐标
        base_shape = SHAPE_CACHE[self.shape_type]
        # 计算缩放后坐标
        self.scaled_shape = [
            (x * self.image.get_width(),
             y * self.image.get_height())
            for (x, y) in base_shape
        ]
        # 绘制主体形状(核心修改)
        pygame.draw.polygon(self.image, RED, self.scaled_shape)
        # 添加动态装饰(30%概率)
        if random.random() < 0.4:
            deco_type = random.choice(["wing", "thruster", "armor", "antenna", "turret"])
            # 在原始形状基础上添加装饰
            if deco_type == "wing":
                # 绘制两侧机翼线
                mid_y = self.image.get_height() // 2
                pygame.draw.line(self.image, ORANGE,
                                 (0, mid_y),
                                 (self.image.get_width(), mid_y), 3)
            elif deco_type == "thruster":
                # 底部推进器
                pygame.draw.circle(self.image, YELLOW,
                                   (self.image.get_width() // 2,
                                    self.image.get_height() - 5), 3)
                flame_color = ORANGE if random.random() < 0.7 else YELLOW
                pygame.draw.polygon(self.image, flame_color, [
                    (self.image.get_width() // 2 - 3, self.image.get_height() - 2),
                    (self.image.get_width() // 2 + 3, self.image.get_height() - 2),
                    (self.image.get_width() // 2, self.image.get_height() + 4)
                ])
            elif deco_type == "armor":
                # 边缘装甲
                pygame.draw.rect(self.image, (100, 100, 100),
                                 (2, 2,
                                  self.image.get_width() - 4,
                                  self.image.get_height() - 4), 2)
            elif deco_type == "antenna":
                # 新增天线装饰
                pygame.draw.line(self.image, CYAN,
                                 (self.image.get_width() // 2, 2),
                                 (self.image.get_width() // 2, -5), 2)
            # 新增炮塔装饰
            elif deco_type == "turret":
                turret_size = 6
                pygame.draw.circle(self.image, (100, 100, 100),
                                   (self.image.get_width() // 2, self.image.get_height() // 2),
                                   turret_size)
                pygame.draw.line(self.image, DARK_GRAY,
                                 (self.image.get_width() // 2 - turret_size, self.image.get_height() // 2),
                                 (self.image.get_width() // 2 + turret_size, self.image.get_height() // 2),
                                 3)

        # 初始化位置和速度(保留原有逻辑)
        self.rect = self.image.get_rect(
            x=random.randrange(WIDTH - self.image.get_width()),
            y=random.randrange(-100, -40)
        )
        self.speedy = random.randrange(4, 8)
        size_factor = 1.5 if size == (30, 25) else 1.2 if size == (35, 30) else 1.0
        self.speedy = int(random.randrange(4, 8) * size_factor)
        # self.image = pygame.Surface(size)
        self.original_color = RED  # 保存原始颜色
        # self.image.fill(RED)
        # pygame.draw.rect(self.image, ORANGE, (0, 0, size[0], 3))
        # 初始化位置和速度(保留原有逻辑)
        self.rect = self.image.get_rect(x=random.randrange(WIDTH - size[0]),
                                        y=random.randrange(-100, -40))
        self.speedy = random.randrange(4, 8)
        # 增加速度变化权重(更大概率获得较大值)
        self.speedx = random.choices(
            [-7, -5, -3, 3, 5, 7],
            weights=[1, 2, 3, 3, 2, 1]
        )[0]
        self.color_phase = random.random() * 2 * math.pi  # 颜色相位
        self.color_speed = random.uniform(0.02, 0.05)  # 颜色变化速度
        self.base_speed = random.randrange(3, 7)  # 基础速度
        self.current_speed = self.base_speed
        self.slow_duration = 0  # 减速剩余时间
        self.is_slowed = False
        # 根据敌机尺寸调整移动参数
        if size == (30, 25):  # 小敌机
            self.speedx *= 1.5
            self.wave_amp = 5  # 波动幅度
        elif size == (40, 35):  # 大敌机
            self.speedx *= 0.8
            self.wave_amp = 2
        self.max_bank_angle = 60  # 最大滚转角(度)
        self.roll_rate = 180  # 滚转角速度(度/秒)
        self.pitch_variation = 30  # 俯仰变化幅度

    def _draw_shape(self):
        shape_actions = {
            'circle': self._draw_circle,
            'triangle': self._draw_triangle,
            'hexagon': self._draw_hexagon,
            'rectangle': self._draw_rectangle
        }
        shape_actions[self.shape_type]()

    def _draw_circle(self):
        pygame.draw.circle(self.image, self.color,
                           (self.radius, self.radius), self.radius)

    def _draw_triangle(self):
        w, h = self.rect.size
        pygame.draw.polygon(self.image, self.color, [
            (0, h), (w // 2, 0), (w, h)
        ])

    def _draw_hexagon(self):
        w, h = self.rect.center
        points = [(w + w // 2 * math.cos(math.radians(60 * i - 30)),
                   h + h // 2 * math.sin(math.radians(60 * i - 30)))
                  for i in range(6)]
        pygame.draw.polygon(self.image, self.color, points)

    def _draw_rectangle(self):
        pygame.draw.rect(self.image, self.color,
                         (0, 0, *self.rect.size), border_radius=random.randint(0, 5))

    def enhanced_evasion(self):
        """增强版规避机动"""
        current_time = pygame.time.get_ticks() / 1000  # 获取秒级时间
        # 复合正弦摆动
        bank_angle = self.max_bank_angle * math.sin(2 * math.pi * 0.5 * current_time)
        pitch_angle = self.pitch_variation * math.sin(2 * math.pi * 0.3 * current_time)

        # 加入随机扰动
        random_factor = 0.2 + 0.8 * random.random()
        return (bank_angle * random_factor, pitch_angle * random_factor)

    def apply_slow(self, duration=5):
        """应用减速效果(默认5秒)"""
        if not self.is_slowed:
            wave_offset = int(3 * math.sin(pygame.time.get_ticks() / 200))
            self.rect.x += wave_offset
            self.current_speed = self.base_speed * 0.5  # 减速50%
            self.slow_duration = duration * FPS  # 转换为帧数
            self.is_slowed = True
            self.image.fill(PURPLE)  # 改变颜色为紫色

    def update(self):
        self.rect.y += self.current_speed
        color_schemes = {
            "triangle": [(255, 50, 50), (200, 0, 0)],  # 红色系
            "diamond": [(50, 50, 255), (0, 0, 200)],  # 蓝色系
            "arrow": [(50, 255, 50), (0, 200, 0)]  # 绿色系
        }
        base_color, accent_color = color_schemes.get(
            self.shape_type, (RED, DARK_RED)
        )
        # 添加金属质感
        for i in range(3):  # 绘制三层颜色增强立体感
            shade_factor = 0.8 + i * 0.1
            current_color = tuple(min(int(c * shade_factor), 255) for c in base_color)
            pygame.draw.polygon(self.image, current_color, self.scaled_shape,
                                width=3 if i == 0 else 1)

            # 动态高光(每5帧更新一次)
        if pygame.time.get_ticks() % 5 == 0:
            highlight_pos = random.choice(self.scaled_shape)
            pygame.draw.circle(self.image, WHITE, highlight_pos, 2)
        # 随机左右移动保持原逻辑
        # self.rect.x += random.randrange(-3, 3) if not self.is_slowed else 0
        if not self.is_slowed:  # 仅在非减速状态使用增强机动
            bank, pitch = self.enhanced_evasion()
            self.rect.x += int(bank / 10)  # 将角度转换为像素位移
            self.rect.y += int(pitch / 20)  # 小幅俯仰位移
        # 动态颜色变化(彩虹效果)
        if not self.is_slowed:
            r = int(127 + 127 * math.sin(self.color_phase))
            g = int(127 + 127 * math.sin(self.color_phase + math.pi / 2))
            b = int(127 + 127 * math.sin(self.color_phase + math.pi))
            self.image.fill((r, g, b, 255))  # 保持不透明
        else:  # 减速时保持紫色
            self.image.fill(PURPLE)
        self.color_phase += self.color_speed
        # 根据形状调整行为
        if self.shape_type == "triangle":
            self.rect.x += random.randint(-5, 5)  # 更大幅度晃动
        elif self.shape_type == "arrow":
            if random.random() < 0.02:  # 2%概率突进
                self.speedy *= 2
        if self.is_slowed:
            self.slow_duration -= 1
            if self.slow_duration <= 0:
                self.current_speed = self.base_speed
                self.is_slowed = False
                self.image.fill(self.original_color)  # 恢复颜色


class Explosion(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.particles = [[list(center),
                           [random.uniform(-3, 3), random.uniform(-5, 0)],
                           random.randint(4, 8)] for _ in range(EXPLOSION_PARTICLES)]
        self.image = pygame.Surface((1, 1))
        self.rect = self.image.get_rect(center=center)
        self.frame = 0

    def update(self):
        self.frame += 1
        if self.frame > 30: self.kill()

    def draw(self, surf):
        for particle in self.particles:
            pos, vel, radius = particle
            pos[0] += vel[0]
            pos[1] += vel[1]
            color = (random.randint(200, 255), random.randint(50, 150), 0)
            pygame.draw.circle(surf, color, (int(pos[0]), int(pos[1])), radius)


# 初始化游戏对象
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
explosions = pygame.sprite.Group()

player = Player()
all_sprites.add(player)


def spawn_enemy():
    enemy = Enemy()
    all_sprites.add(enemy)
    enemies.add(enemy)


for _ in range(8): spawn_enemy()

# 游戏状态
running = True
game_over = False
score = 0
high_score = read_high_score()
enemy_spawn_timer = 0

# 字体设置
font = pygame.font.Font(font_path, 36)
game_over_font = pygame.font.Font(font_path, 72)
final_score_font = pygame.font.Font(font_path, 48)

powerups = pygame.sprite.Group()  # 新增道具组
# 主游戏循环
while running:
    clock.tick(FPS)
    powerup_hits = pygame.sprite.spritecollide(player, powerups, True)
    for powerup in powerup_hits:
        if powerup.type == 'shield':
            # 实现无敌效果(比如临时无敌)
            player.shield = True
            # player.shield_time = pygame.time.get_ticks() + 8000  # 8秒无敌
            pygame.time.set_timer(pygame.USEREVENT + 2, 0)
            pygame.time.set_timer(pygame.USEREVENT + 2, 10000)  # 使用不同事件ID
            player.powerup_text = "无敌激活!"
            player.update_plane_color()  # 新增立即更新
        elif powerup.type == 'double':
            # 双倍火力
            player.double_fire = True
            player.shoot_delay = 150  # 射速提升更明显
            pygame.time.set_timer(pygame.USEREVENT + 1, 0)
            pygame.time.set_timer(pygame.USEREVENT + 1, 10000)  # 使用不同事件ID
            player.powerup_text = "双倍火力!"
        elif powerup.type == 'life':
            # 增加生命值
            player.lives += 1
            player.powerup_text = "生命+1!"
        elif powerup.type == 'ricochet':
            player.ricochet_active = True
            pygame.time.set_timer(pygame.USEREVENT + 3, 0)
            pygame.time.set_timer(pygame.USEREVENT + 3, 10000)  # 使用不同事件ID
            player.powerup_text = "子弹弹射激活!"
            # 为现有子弹添加效果
            for bullet in bullets:
                bullet.speedx = random.choice([-3, 3])  # 随机初始水平速度
                bullet.ricochet = True
                bullet.image.fill(CYAN)
        elif powerup.type == 'rage':
            # 狂暴状态激活
            player.rage_active = True
            player.shoot_delay = 100  # 射速提升60%
            pygame.time.set_timer(pygame.USEREVENT + 4, 0)  # 清除旧计时器
            pygame.time.set_timer(pygame.USEREVENT + 4, 5000)  # 持续5秒
            player.powerup_text = "狂暴激活!射速提升!"
        elif powerup.type == 'slow':
            # 减速所有敌机
            for enemy in enemies:
                enemy.apply_slow(5)  # 5秒减速
            pygame.time.set_timer(pygame.USEREVENT + 5, 0)  # 清除旧计时器
            pygame.time.set_timer(pygame.USEREVENT + 5, 5000)  # 使用事件ID+5
            player.powerup_text = "敌机减速!"
        elif powerup.type == 'triple':
            player.triple_fire = True
            player.triple_start_time = pygame.time.get_ticks()  # 记录启动时间
            pygame.time.set_timer(pygame.USEREVENT + 6, 5000)
            player.powerup_text = "三向射击激活!"
            player.triple_shot()  # 立即触发一次三向射击
        elif powerup.type == 'confusion':
            player.confused = True
            player.confuse_start = pygame.time.get_ticks()
            player.powerup_text = "方向感混乱!"
            player.text_timer = pygame.time.get_ticks()

            # 设置定时器
            pygame.time.set_timer(pygame.USEREVENT + 7, 5000)

            # 添加扭曲粒子
            particles = Explosion(powerup.rect.center)
            particles.particles = [
                [list(powerup.rect.center),
                 [random.uniform(-3, 3), random.uniform(-3, 3)],
                 3,
                 CONFUSION_PURPLE]
                for _ in range(15)
            ]
            all_sprites.add(particles)
        elif powerup.type == 'blackhole':
            player.blackhole_active = True
            player.blackhole_start_time = pygame.time.get_ticks()
            player.powerup_text = "黑洞激活!"
            player.text_timer = pygame.time.get_ticks()

            # 设置定时器
            pygame.time.set_timer(pygame.USEREVENT + 8, 7000)  # 7秒后失效

            # 添加特殊粒子效果
            blackhole_particles = Explosion(powerup.rect.center)
            blackhole_particles.particles = [
                [list(powerup.rect.center),
                 [random.uniform(-2, 2), random.uniform(-2, 2)],
                 3,
                 BLACK_HOLE_COLOR]
                for _ in range(20)
            ]
            all_sprites.add(blackhole_particles)

        player.text_timer = pygame.time.get_ticks()

        # 添加拾取特效
        for _ in range(10):
            particle = Explosion(powerup.rect.center)
            particle.particles = [[list(powerup.rect.center),
                                   [random.uniform(-2, 2), random.uniform(-5, 0)],
                                   3] for _ in range(8)]
            all_sprites.add(particle)
    # 在主循环中添加无敌检测
    # if player.shield and pygame.time.get_ticks() > player.shield_time:
    #     player.shield = False
    #     player.update_plane_color()  # 新增颜色恢复
    #     if player.powerup_text == "无敌激活!":
    #         player.powerup_text = "无敌已失效!"
    # player.draw_shield()  # 绘制无敌

    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.USEREVENT + 8:
            pygame.time.set_timer(pygame.USEREVENT + 8, 0)
            if player.blackhole_active:
                player.blackhole_active = False
                player.powerup_text = "黑洞消失!"
                player.text_timer = pygame.time.get_ticks()
        if event.type == pygame.USEREVENT + 7:
            pygame.time.set_timer(pygame.USEREVENT + 7, 0)
            if player.confused:
                player.confused = False
                player.powerup_text = "方向感恢复!"
                player.text_timer = pygame.time.get_ticks()
        # 新增三向射击结束事件
        if event.type == pygame.USEREVENT + 6:
            player.triple_fire = False
            player.powerup_text = "三向射击结束"
            player.text_timer = pygame.time.get_ticks()
            pygame.time.set_timer(pygame.USEREVENT + 6, 0)  # 关闭计时器
        # 在减速结束事件中添加特效
        if event.type == pygame.USEREVENT + 5:
            # 恢复所有敌机原始状态
            for enemy in enemies:
                if enemy.is_slowed:
                    enemy.current_speed = enemy.base_speed
                    enemy.is_slowed = False
                    enemy.image.fill(enemy.original_color)
                    # 添加解除特效
                    frost_break = Explosion(enemy.rect.center)
                    frost_break.particles = [
                        [list(enemy.rect.center),
                         [random.uniform(-2, 2), random.uniform(-2, 2)],
                         3,  # 粒子半径
                         PURPLE  # 紫色粒子
                         ] for _ in range(8)
                    ]
                    all_sprites.add(frost_break)

            player.powerup_text = "减速效果结束"
            player.text_timer = pygame.time.get_ticks()
            pygame.time.set_timer(pygame.USEREVENT + 5, 0)  # 关闭计时器

        if event.type == pygame.USEREVENT + 2:
            player.shield = False
            player.update_plane_color()  # 新增颜色恢复
            player.powerup_text = "无敌已失效!"
            player.draw_shield()  # 绘制无敌
            player.text_timer = pygame.time.get_ticks()  # 必须重置计时器
            pygame.time.set_timer(pygame.USEREVENT + 2, 0)  # 关闭计时器
        if event.type == pygame.USEREVENT + 4:
            player.rage_active = False
            player.shoot_delay = player.original_shoot_delay
            player.powerup_text = "狂暴状态结束"
            player.text_timer = pygame.time.get_ticks()
            pygame.time.set_timer(pygame.USEREVENT + 4, 0)  # 关闭计时器
        if event.type == pygame.USEREVENT + 3:  # 弹射结束事件
            player.ricochet_active = False
            # 恢复子弹颜色
            for bullet in bullets:
                if not bullet.ricochet:
                    bullet.image.fill(ORANGE if bullet.is_double else YELLOW)
            player.powerup_text = "弹射效果结束"
            player.text_timer = pygame.time.get_ticks()  # 必须重置计时器
            pygame.time.set_timer(pygame.USEREVENT + 3, 0)  # 关闭计时器
        # 新增双倍火力结束事件
        if event.type == pygame.USEREVENT + 1:
            player.double_fire = False
            player.shoot_delay = 250  # 恢复原始射速
            # 新增状态重置 ↓
            player.powerup_text = "火力恢复普通状态!"
            player.text_timer = pygame.time.get_ticks()  # 必须重置计时器
            pygame.time.set_timer(pygame.USEREVENT + 1, 0)  # 关闭计时器
        # 新增鼠标点击事件处理
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            mouse_pos = pygame.mouse.get_pos()
            # 检测重玩按钮点击 (坐标需与文本位置匹配)
            if WIDTH // 2 - 60 <= mouse_pos[0] <= WIDTH // 2 + 60 and \
                    HEIGHT // 2 + 80 <= mouse_pos[1] <= HEIGHT // 2 + 120:
                # 执行重置逻辑(复用原R键代码)
                all_sprites.empty()
                enemies.empty()
                bullets.empty()
                explosions.empty()
                player = Player()
                all_sprites.add(player)
                for _ in range(8): spawn_enemy()
                score = 0
                player.powerup_text = ""  # 新增重置文字状态
                enemy_spawn_timer = 0
                game_over = False
            # 检测退出按钮点击
            elif WIDTH // 2 - 60 <= mouse_pos[0] <= WIDTH // 2 + 60 and \
                    HEIGHT // 2 + 120 <= mouse_pos[1] <= HEIGHT // 2 + 160:
                running = False
        if game_over and event.type == pygame.KEYDOWN:
            if event.key in (pygame.K_r, pygame.K_SPACE):  # 重置游戏
                all_sprites.empty()
                enemies.empty()
                bullets.empty()
                explosions.empty()
                player = Player()
                all_sprites.add(player)
                for _ in range(8): spawn_enemy()
                score = 0
                player.powerup_text = ""  # 新增重置文字状态
                enemy_spawn_timer = 0
                game_over = False
            elif event.key in (pygame.K_q, pygame.K_KP_ENTER, pygame.K_RETURN):
                running = False

    if not game_over:
        # 游戏逻辑
        enemy_spawn_timer += 1
        if enemy_spawn_timer > 45:
            spawn_enemy()
            enemy_spawn_timer = 0

        all_sprites.update()

        # 碰撞检测
        hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
        for hit in hits:
            score += 50
            explosion = Explosion(hit.rect.center)
            all_sprites.add(explosion)
            explosions.add(explosion)

            # 新增道具掉落(80%概率)
            if random.random() < 0.8:
                powerup = PowerUp(hit.rect.center)
                all_sprites.add(powerup)
                powerups.add(powerup)

        # 检测道具拾取
        if pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_rect_ratio(0.8)):
            if not player.shield:
                #  生命减1
                player.lives -= 1
                # 游戏结束
                if player.lives <= 0:  # 只有生命值为 0 时才结束游戏
                    if score > high_score:
                        high_score = score
                        write_high_score(high_score)
                    game_over = True

    # 绘制
    screen.fill(BLACK)
    # 绘制星空背景
    for star in stars:
        star.update()  # 确保调用更新方法
        pygame.draw.circle(screen, STAR_COLOR, (int(star.x), int(star.y)), star.size)
        # 绘制流星尾迹
        if star.is_meteor:
            for i, pos in enumerate(star.tail):
                alpha = 255 - i * 25
                pygame.draw.line(screen, (255, 255, 255, alpha),
                                 pos, (star.x, star.y), 2)

        # 重置位置检查
        if star.y > HEIGHT + 10:
            star.reset()

    all_sprites.draw(screen)
    for explosion in explosions:
        explosion.draw(screen)
    # 实时生成文本(必须在每帧循环内)
    score_text = font.render(f"Score: {score}", True, WHITE)  # ✅ 移到循环内
    high_score_text = font.render(f"High Score: {high_score}", True, YELLOW)
    life_text = font.render(f"Lives: {player.lives}", True, GREEN)
    # 绘制其他元素
    screen.blit(score_text, (10, 10))
    screen.blit(high_score_text, (10, 50))
    life_rect = life_text.get_rect(topright=(WIDTH - 10, 10))
    screen.blit(life_text, life_rect)

    # 添加道具提示文字(在游戏结束界面之前)
    # 修改道具提示绘制逻辑(约459-467行)
    if pygame.time.get_ticks() - player.text_timer < 2500 and player.powerup_text:
        # 立即显示后开始闪烁(500ms后开始闪烁)
        if (pygame.time.get_ticks() - player.text_timer < 500) or \
                ((pygame.time.get_ticks() // 250) % 2 == 0):
            text_surf = font.render(player.powerup_text, True, YELLOW)
            text_rect = text_surf.get_rect(center=(WIDTH // 2, HEIGHT - 100))
            bg_rect = text_rect.inflate(20, 10)
            pygame.draw.rect(screen, (0, 0, 0, 180), bg_rect)
            screen.blit(text_surf, text_rect)

    # 游戏结束界面
    if game_over:
        overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
        overlay.fill(OVERLAY_COLOR)
        screen.blit(overlay, (0, 0))

        game_over_text = game_over_font.render("坠机!", True, RED)
        text_rect = game_over_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 80))
        screen.blit(game_over_text, text_rect)

        final_score = final_score_font.render(f"本次得分: {score}", True, WHITE)
        screen.blit(final_score, final_score.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 20)))

        controls = [
            ("R/空格 - 重玩", GREEN),
            ("Q/回车 - 退出", RED)
        ]

        for i, (text, color) in enumerate(controls):
            text_surf = font.render(text, True, color)
            # 获取文本矩形并设置水平居中
            text_rect = text_surf.get_rect(centerx=WIDTH // 2,
                                           y=HEIGHT // 2 + 80 + i * 40)
            screen.blit(text_surf, text_rect)

    pygame.display.flip()

pygame.quit()

总结 

各位大佬如果有什么好的想法可以在评论区留言,整体来说还是非常消耗时间的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

封奚泽优

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值