类似代码
外星人入侵(python)_外星人入侵python源代码-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/135963588?spm=1001.2014.3001.5501贪吃蛇(含Python源码)_python写贪吃蛇源码-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147660127?spm=1001.2014.3001.5501像素飞机大战(含Python源码)_像素版飞机大战代码-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147693018?spm=1001.2014.3001.55012048游戏(含Python源码)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147711281?spm=1001.2014.3001.5501使用DeepSeek定制Python小游戏——以“俄罗斯方块”为例_用deepseek做俄罗斯方块游戏-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/147686449?spm=1001.2014.3001.5501优化俄罗斯方块小游戏-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/148284156?spm=1001.2014.3001.5502
代码
玩家可通过按下Esc键触发游戏暂停,如果各位大佬有发现代码的问题或者对于特殊道具有新想法的欢迎在评论区进行留言。
import random
from typing import TypeVar
import pygame
import math
# 封奚泽优
TSprite = TypeVar('TSprite', bound=pygame.sprite.Sprite)
# 高分文件路径
HIGHSCORE_FILE = "highscore.txt"
EXPLOSION_PARTICLES = 20 # 爆炸粒子数量
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) # 灰色
VERTICAL_BULLET_COLOR = (100, 200, 255) # 淡蓝色
MAGENTA = (255, 0, 255) # 品红色 - 用于反向射击道具
TRACKING_COLOR = (0, 255, 0) # 亮绿色 - 用于跟踪子弹道具
SILENCE_COLOR = (128, 0, 128) # 深紫色 - 用于沉默道具
ORANGE = (255, 165, 0) # 橙色道具
LIGHT_BLUE = (173, 216, 230) # 新增浅蓝色定义
AUTO_FIRE_COLOR = (255, 105, 180) # 新增自动发射道具颜色(亮粉色)
VERTICAL_FIRE_COLOR = (128, 0, 128) # 深紫色 - 用于垂直火力道具
PARALYZE_COLOR = (70, 130, 180) # 钢蓝色 - 用于麻痹道具
SPLIT_COLOR = (255, 140, 0) # 深橙色 - 用于分裂射击道具
# 初始化窗口
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)],
# 六边形
[(-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)],
# 飞碟形状
[(-15, -5), (-10, -10), (10, -10), (15, -5),
(10, 5), (-10, 5), (-15, -5), (-5, 5), (5, 5)],
# 战斗机形状
[(-20, 0), (-15, -10), (0, -15), (15, -10), (20, 0),
(15, 5), (0, 10), (-15, 5), (-20, 0)],
# 太空船形状
[(-10, -10), (-5, -15), (5, -15), (10, -10),
(15, 0), (10, 10), (-10, 10), (-15, 0), (-10, -10)],
# 蝙蝠形状
[(-15, 0), (-10, -8), (0, -10), (10, -8), (15, 0),
(10, 8), (0, 10), (-10, 8), (-15, 0)],
# 箭头形状
[(-10, -10), (0, -15), (10, -10), (0, 15)],
# 十字形
[(-10, -5), (-5, -5), (-5, -10), (5, -10), (5, -5), (10, -5),
(10, 5), (5, 5), (5, 10), (-5, 10), (-5, 5), (-10, 5)]
]
# 在游戏状态区域添加星空初始化
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.penetrate_active = False # 新增穿透状态
self.penetrate_timer = 0 # 穿透状态结束时间
self.reverse_fire = False # 新增反向射击状态
self.reverse_fire_timer = 0 # 反向射击持续时间
self.tracking_active = False # 新增跟踪状态
self.tracking_timer = 0 # 跟踪状态持续时间
self.tracking_target = None # 新增缺失属性
# 添加沉默状态属性
self.silenced = False # 新增沉默状态
self.silence_timer = 0 # 沉默状态持续时间
self.auto_fire = False # 自动发射状态
self.auto_fire_timer = 0 # 自动发射持续时间
self.last_auto_shot = 0 # 上次自动发射时间
self.split_active = False # 新增分裂射击状态
self.split_timer = 0 # 分裂状态持续时间
# 新增类属性保存坐标点
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秒
self.vertical_fire = False # 新增属性初始化
self.paralyzed = False # 新增麻痹状态
self.paralyze_timer = 0 # 麻痹状态持续时间
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)
blur_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA) # 将模糊表面移出循环
time_factor = pygame.time.get_ticks() / 100
# 减少粒子密度:将步长从20改为40
for x in range(0, WIDTH, 40):
for y in range(0, HEIGHT, 40):
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)
)
# 径向模糊 - 移出循环
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))
# 确保震动强度非负
effective_intensity = max(0, shake_intensity) # 负数自动归零
if shake_intensity > 0: # 确保参数有效
y_shake = random.randint(-shake_intensity, shake_intensity)
x_shake = random.randint(-shake_intensity, shake_intensity)
else: # 处理无效值
x_shake = 0
y_shake = 0
# 组合所有效果 - 只调用一次blit
screen.blit(distortion_surface, (x_shake, y_shake))
screen.blit(blur_surface, (x_shake, y_shake))
def update(self):
keys = pygame.key.get_pressed()
if self.paralyzed: # 麻痹状态下无法移动
# 只更新颜色和特效,不处理移动
self.update_plane_color()
return
# 修改移动逻辑
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()
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 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
if self.auto_fire:
self.auto_fire_timer -= 1
if self.auto_fire_timer <= 0:
self.auto_fire = False
if self.vertical_fire:
# 添加垂直火力状态指示器
indicator = font.render("垂直火力激活", True, VERTICAL_FIRE_COLOR)
screen.blit(indicator, (WIDTH // 2 - 60, 20))
# 玩家射击
def shoot(self):
if self.vertical_fire:
# 垂直火力子弹从飞机底部发射
y_pos = self.rect.bottom
else:
# 普通子弹从飞机顶部发射
y_pos = self.rect.top
if self.silenced: # 沉默状态下无法射击
return
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:
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,
'penetrate': self.penetrate_active, # 新增穿透状态
'tracking': self.tracking_active, # 新增跟踪状态
'vertical_fire': self.vertical_fire,
}
# 双倍火力时发射两发子弹
bullets_to_add = [
Bullet(self.rect.centerx - offset, y_pos, **bullet_props), # 使用调整后的y_pos
Bullet(self.rect.centerx + offset, y_pos, **bullet_props)
] if self.double_fire else [
Bullet(self.rect.centerx, y_pos, **bullet_props) # 使用调整后的y_pos
]
# 弹射时填充弹射颜色
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))
# 沉默状态下添加锁图标
if self.silenced:
lock_surf = pygame.Surface((15, 15), pygame.SRCALPHA)
pygame.draw.rect(lock_surf, SILENCE_COLOR, (0, 0, 15, 15))
pygame.draw.arc(lock_surf, SILENCE_COLOR, (3, 0, 9, 9), 0, math.pi, 2)
pygame.draw.rect(lock_surf, SILENCE_COLOR, (6, 6, 3, 6))
self.image.blit(lock_surf, (PLAYER_WIDTH // 2 - 7, PLAYER_HEIGHT - 20))
if self.paralyzed:
# 添加锁链覆盖效果
chain_overlay = pygame.Surface((PLAYER_WIDTH, PLAYER_HEIGHT), pygame.SRCALPHA)
# 绘制横向锁链
for y in range(5, PLAYER_HEIGHT, 10):
pygame.draw.line(chain_overlay, PARALYZE_COLOR,
(0, y), (PLAYER_WIDTH, y), 2)
# 绘制链环
for x in range(5, PLAYER_WIDTH, 10):
pygame.draw.circle(chain_overlay, PARALYZE_COLOR, (x, y), 3, 1)
self.image.blit(chain_overlay, (0, 0))
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, is_double=False, ricochet=False, speedx=0, speedy=None, penetrate=False, tracking=False,
vertical_fire=False):
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
self.penetrate = penetrate # 是否可穿透
self.penetrate_count = 0 # 穿透计数
# 修改速度初始化逻辑
if speedy is not None: # 如果传入了speedy参数
self.speedy = speedy
else: # 保持原有逻辑
self.speedy = -12 if is_double else -10
self.tracking = tracking # 是否具有跟踪能力
self.tracking_strength = 0.1 # 跟踪强度
if tracking:
self.image.fill(TRACKING_COLOR)
pygame.draw.line(self.image, WHITE, (0, BULLET_SIZE), (BULLET_SIZE, 0), 1) # 十字准星
self.vertical_fire = vertical_fire # 新增属性初始化
if vertical_fire:
self.speedy = 10
self.rect = self.image.get_rect(centerx=x, bottom=y)
elif speedy is not None:
self.speedy = speedy
self.rect = self.image.get_rect(centerx=x, top=y) # 三向子弹
else:
self.speedy = -12 if is_double else -10
self.rect = self.image.get_rect(centerx=x, top=y) # 普通子弹
# 添加垂直火力颜色标识 ↓
if vertical_fire:
self.image.fill(VERTICAL_FIRE_COLOR) # 使用垂直火力颜色
# 添加向下箭头标识
pygame.draw.line(self.image, WHITE,
(BULLET_SIZE // 2, 0),
(BULLET_SIZE // 2, BULLET_SIZE * 2), 2)
def update(self):
# 跟踪逻辑
if self.tracking and enemies:
# 找到最近的敌机
closest_enemy = None
min_distance = float('inf')
for enemy in enemies:
dx = enemy.rect.centerx - self.rect.centerx
dy = enemy.rect.centery - self.rect.centery
distance = math.hypot(dx, dy)
if distance < min_distance:
min_distance = distance
closest_enemy = enemy
# 向最近敌机移动
if closest_enemy and min_distance < 300:
dx = closest_enemy.rect.centerx - self.rect.centerx
dy = closest_enemy.rect.centery - self.rect.centery
dist = math.hypot(dx, dy)
if dist > 0:
self.speedx += dx / dist * self.tracking_strength
self.speedy += dy / dist * self.tracking_strength
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.penetrate:
# 每5帧创建一个尾迹粒子
if pygame.time.get_ticks() % 5 == 0:
trail = Explosion(self.rect.center)
trail.particles = [[list(self.rect.center),
[random.uniform(-0.5, 0.5), random.uniform(-0.5, 0.5)],
2,
(138, 43, 226)] # 紫罗兰色
for _ in range(3)]
all_sprites.add(trail)
if self.rect.bottom < 0:
self.kill()
# 垂直火力子弹边界检查
if self.vertical_fire:
# 当子弹超出屏幕底部时,重置到屏幕顶部
if self.rect.top > HEIGHT:
# 保持水平位置不变,垂直位置重置到屏幕顶部上方
self.rect.bottom = 0 # 从屏幕顶部出现
# 可选:添加粒子效果表示穿越
particles = Explosion((self.rect.centerx, HEIGHT))
particles.particles = [
[list((self.rect.centerx, HEIGHT)),
[random.uniform(-2, 2), random.uniform(-5, -2)],
3,
VERTICAL_FIRE_COLOR]
for _ in range(8)
]
all_sprites.add(particles)
# 修改边界检查逻辑
if self.vertical_fire and self.rect.top > HEIGHT * 2:
# 连续两次超出屏幕才销毁(给穿越一次机会)
self.kill()
elif not self.vertical_fire and self.rect.bottom < 0:
self.kill()
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
# 随机选择敌机尺寸
size = random.choice(ENEMY_SIZES)
self.shape_scale = random.uniform(0.8, 1.2) # 随机缩放比例
# 从SHAPE_TEMPLATES中随机选择形状模板
template = random.choice(SHAPE_TEMPLATES)
# 计算模板的边界
min_x = min(point[0] for point in template)
max_x = max(point[0] for point in template)
min_y = min(point[1] for point in template)
max_y = max(point[1] for point in template)
width_range = max_x - min_x
height_range = max_y - min_y
# 创建带透明通道的表面
self.image = pygame.Surface(
(int(size[0] * self.shape_scale),
int(size[1] * self.shape_scale)),
pygame.SRCALPHA
)
# 将模板点缩放到表面大小
self.scaled_shape = []
for x, y in template:
# 归一化到0-1范围
norm_x = (x - min_x) / width_range
norm_y = (y - min_y) / height_range
# 缩放到表面尺寸
scaled_x = norm_x * self.image.get_width()
scaled_y = norm_y * self.image.get_height()
self.scaled_shape.append((scaled_x, scaled_y))
# 随机生成主色和辅色
self.primary_color = tuple(random.randint(100, 255) for _ in range(3))
self.secondary_color = tuple(
min(255, c + random.randint(-50, 50))
for c in self.primary_color
)
# 绘制主体形状
pygame.draw.polygon(self.image, self.primary_color, self.scaled_shape)
# 添加内部细节(根据形状复杂度)
if len(template) > 4: # 复杂形状
# 绘制内部多边形
inner_points = []
for point in self.scaled_shape:
# 向中心收缩20%
center_x = self.image.get_width() / 2
center_y = self.image.get_height() / 2
inner_x = point[0] * 0.8 + center_x * 0.2
inner_y = point[1] * 0.8 + center_y * 0.2
inner_points.append((inner_x, inner_y))
pygame.draw.polygon(self.image, self.secondary_color, inner_points, 2)
# 添加驾驶舱效果
cockpit_center = (self.image.get_width() // 2, self.image.get_height() // 3)
pygame.draw.circle(self.image, (200, 200, 255), cockpit_center, 4)
pygame.draw.circle(self.image, (100, 100, 200), cockpit_center, 2)
# 添加动态装饰(40%概率)
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)
)
# 根据敌机尺寸调整移动参数
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.original_color = self.primary_color # 保存原始颜色
# 速度变化权重(更大概率获得较大值)
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 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:
self.current_speed = self.base_speed * 0.5 # 减速50%
self.slow_duration = duration * FPS # 转换为帧数
self.is_slowed = True
# 创建减速特效表面
frost_overlay = pygame.Surface(self.image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(frost_overlay, (*PURPLE, 100), self.scaled_shape)
self.image.blit(frost_overlay, (0, 0))
def update(self):
self.rect.y += self.current_speed
# 随机左右移动
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))
# 创建新的表面应用颜色效果
colored_surface = pygame.Surface(self.image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(colored_surface, (r, g, b, 255), self.scaled_shape)
self.image.blit(colored_surface, (0, 0))
# 保持驾驶舱和装饰
cockpit_center = (self.image.get_width() // 2, self.image.get_height() // 3)
pygame.draw.circle(self.image, (200, 200, 255), cockpit_center, 4)
pygame.draw.circle(self.image, (100, 100, 200), cockpit_center, 2)
# 处理减速状态
if self.is_slowed:
self.slow_duration -= 1
if self.slow_duration <= 0:
self.current_speed = self.base_speed
self.is_slowed = False
# 恢复原始颜色
colored_surface = pygame.Surface(self.image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(colored_surface, self.original_color, self.scaled_shape)
self.image.blit(colored_surface, (0, 0))
self.color_phase += self.color_speed
# 如果敌机飞出屏幕底部,重新生成
if self.rect.top > HEIGHT:
self.kill()
spawn_enemy()
class PowerUp(pygame.sprite.Sprite):
TYPES = ['shield', 'double', 'life', 'ricochet', 'rage', 'slow', 'triple', 'confusion', 'blackhole', 'penetrate',
'tracking', 'silence', 'auto_fire', 'vertical_fire', 'paralyze', 'split']
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,
'penetrate': (138, 43, 226), 'auto_fire': AUTO_FIRE_COLOR, 'vertical_fire': VERTICAL_FIRE_COLOR}
# 创建不同形状的道具
self.image = pygame.Surface((40, 40), pygame.SRCALPHA) # 增大尺寸以容纳更复杂的形状
if self.type == 'shield':
# 盾牌形状 - 更立体的设计
pygame.draw.circle(self.image, colors[self.type], (15, 15), 12) # 外圈
pygame.draw.circle(self.image, (255, 255, 200), (15, 15), 8) # 内圈
# 添加十字保护符号
pygame.draw.line(self.image, colors[self.type], (15, 8), (15, 22), 3)
pygame.draw.line(self.image, colors[self.type], (8, 15), (22, 15), 3)
# 添加光泽效果
pygame.draw.arc(self.image, (255, 255, 255, 150), (5, 5, 20, 20), 0, math.pi / 2, 2)
elif self.type == 'double':
center_x, center_y = 20, 20
# 绘制能量核心 - 旋转的橙色光球
core_radius = 8
pygame.draw.circle(self.image, (255, 165, 0, 200), (center_x, center_y), core_radius)
# 添加核心旋转效果(随时间旋转的亮点)
rotation_angle = math.radians(pygame.time.get_ticks() / 10 % 360)
highlight_x = center_x + core_radius * 0.6 * math.cos(rotation_angle)
highlight_y = center_y + core_radius * 0.6 * math.sin(rotation_angle)
pygame.draw.circle(self.image, (255, 255, 200), (int(highlight_x), int(highlight_y)), 3)
# 绘制双子弹 - 立体设计
bullet_size = 6
# 第一颗子弹(较大)
pygame.draw.polygon(self.image, ORANGE, [
(center_x - bullet_size, center_y - bullet_size),
(center_x + bullet_size, center_y - bullet_size),
(center_x + bullet_size, center_y + bullet_size),
(center_x - bullet_size, center_y + bullet_size)
])
# 添加子弹高光
pygame.draw.line(self.image, (255, 200, 100),
(center_x - bullet_size + 2, center_y - bullet_size + 2),
(center_x + bullet_size - 2, center_y - bullet_size + 2), 1)
# 第二颗子弹(旋转45度,叠加效果)
rotated_bullet = [
(center_x, center_y - bullet_size * 1.5),
(center_x + bullet_size * 1.5, center_y),
(center_x, center_y + bullet_size * 1.5),
(center_x - bullet_size * 1.5, center_y)
]
pygame.draw.polygon(self.image, (255, 100, 0), rotated_bullet)
# 添加能量涌动效果(动态粒子)
now = pygame.time.get_ticks()
if (now // 100) % 3 == 0: # 每300ms变化一次
for i in range(8):
angle = math.radians(i * 45 + now / 20 % 360)
distance = core_radius + 5 + (i % 2) * 3
x = center_x + distance * math.cos(angle)
y = center_y + distance * math.sin(angle)
size = 1 + (i % 3)
pygame.draw.circle(self.image, (255, 200, 0, 200), (int(x), int(y)), size)
# 添加火力倍增符号(旋转的"x2")
if (now // 150) % 2 == 0: # 闪烁效果
text_surf = pygame.font.SysFont(None, 24).render("x2", True, (255, 255, 200))
text_rect = text_surf.get_rect(center=(center_x, center_y))
self.image.blit(text_surf, text_rect)
elif self.type == 'life':
# 心形生命符号 - 更圆润的设计
pygame.draw.circle(self.image, colors[self.type], (10, 10), 6) # 左半圆
pygame.draw.circle(self.image, colors[self.type], (20, 10), 6) # 右半圆
pygame.draw.polygon(self.image, colors[self.type], [
(5, 12), (25, 12), (15, 25)
])
# 添加光泽效果
pygame.draw.arc(self.image, (255, 255, 255, 180), (8, 5, 5, 5), 0, math.pi / 2, 1)
elif self.type == 'ricochet':
# 优化后的弹射子弹设计:更生动的弹跳效果
# 绘制墙壁
pygame.draw.rect(self.image, (100, 100, 100), (5, 5, 30, 30), 2) # 边界框
# 绘制弹跳点
bounce_point = (20, 20)
pygame.draw.circle(self.image, CYAN, bounce_point, 6)
# 绘制子弹和弹道
now = pygame.time.get_ticks()
phase = (now // 100) % 4 # 4个动画阶段
if phase == 0: # 初始位置
pygame.draw.circle(self.image, CYAN, (10, 25), 4)
pygame.draw.line(self.image, CYAN, (10, 25), bounce_point, 2)
elif phase == 1: # 接触点
pygame.draw.circle(self.image, WHITE, bounce_point, 5)
# 添加碰撞特效
for i in range(3):
angle = math.radians(45 + i * 90)
end_x = bounce_point[0] + 8 * math.cos(angle)
end_y = bounce_point[1] + 8 * math.sin(angle)
pygame.draw.line(self.image, WHITE, bounce_point, (end_x, end_y), 1)
elif phase == 2: # 弹射后
pygame.draw.circle(self.image, CYAN, (30, 15), 4)
pygame.draw.line(self.image, CYAN, bounce_point, (30, 15), 2)
else: # 第二个弹射点
pygame.draw.circle(self.image, CYAN, (15, 10), 4)
pygame.draw.line(self.image, CYAN, (30, 15), (15, 10), 2)
# 添加弹射标记
pygame.draw.polygon(self.image, WHITE, [
(bounce_point[0], bounce_point[1] - 8),
(bounce_point[0] + 5, bounce_point[1] - 3),
(bounce_point[0] - 5, bounce_point[1] - 3)
])
elif self.type == 'rage':
# 火焰形状 - 更生动的火焰
# 火焰主体
pygame.draw.polygon(self.image, colors[self.type], [
(15, 5), (20, 10), (18, 15),
(20, 20), (15, 25),
(10, 20), (12, 15), (10, 10)
])
# 内部火焰
pygame.draw.polygon(self.image, ORANGE, [
(15, 10), (17, 13), (16, 17),
(17, 20), (15, 22),
(13, 20), (14, 17), (13, 13)
])
# 火花效果
for i in range(3):
x = random.randint(5, 25)
y = random.randint(5, 10)
pygame.draw.circle(self.image, YELLOW, (x, y), 2)
elif self.type == 'slow':
# 沙漏形状 - 更精细的设计
# 上部分
pygame.draw.polygon(self.image, colors[self.type], [
(10, 5), (20, 5), (15, 12)
])
# 下部分
pygame.draw.polygon(self.image, colors[self.type], [
(10, 25), (20, 25), (15, 18)
])
# 中间连接
pygame.draw.line(self.image, colors[self.type], (15, 12), (15, 18), 3)
# 添加流动的沙子
pygame.draw.circle(self.image, (200, 200, 0), (15, 14), 3)
pygame.draw.circle(self.image, (200, 200, 0), (13, 16), 2)
elif self.type == 'triple':
# 三向射击 - 更明显的方向指示
angles = [0, 120, 240]
for angle in angles:
rad = math.radians(angle)
end_x = 15 + 10 * math.cos(rad)
end_y = 15 + 10 * math.sin(rad)
# 绘制箭头
pygame.draw.line(self.image, colors[self.type], (15, 15), (end_x, end_y), 3)
# 箭头头部
head_angle = math.radians(angle - 30)
head_x1 = end_x + 5 * math.cos(head_angle)
head_y1 = end_y + 5 * math.sin(head_angle)
head_angle = math.radians(angle + 30)
head_x2 = end_x + 5 * math.cos(head_angle)
head_y2 = end_y + 5 * math.sin(head_angle)
pygame.draw.polygon(self.image, colors[self.type], [
(end_x, end_y), (head_x1, head_y1), (head_x2, head_y2)
])
elif self.type == 'confusion':
# 混乱状态 - 螺旋线加旋转箭头
# 彩色螺旋线
for i in range(3, 0, -1):
rect = pygame.Rect(5 * i, 5 * i, 30 - 10 * i, 30 - 10 * i)
color = (CONFUSION_BLUE if i % 2 == 1 else CONFUSION_PURPLE)
pygame.draw.arc(self.image, color, rect, 0, math.pi * 2, 3)
# 旋转箭头
angle = pygame.time.get_ticks() / 20 % 360
rad = math.radians(angle)
end_x = 15 + 8 * math.cos(rad)
end_y = 15 + 8 * math.sin(rad)
pygame.draw.line(self.image, WHITE, (15, 15), (end_x, end_y), 2)
# 箭头头部
pygame.draw.polygon(self.image, WHITE, [
(end_x, end_y),
(end_x + 4 * math.cos(rad - math.pi / 6), end_y + 4 * math.sin(rad - math.pi / 6)),
(end_x + 4 * math.cos(rad + math.pi / 6), end_y + 4 * math.sin(rad + math.pi / 6))
])
elif self.type == 'blackhole':
# 优化后的黑洞设计:简洁而强大的视觉效果
center_x, center_y = 20, 20
# 绘制吸积盘 - 更真实的物理表现
inner_radius = 8
outer_radius = 18
# 创建吸积盘渐变色
for r in range(inner_radius, outer_radius):
# 计算颜色强度(内圈更亮)
intensity = int(150 * (1 - (r - inner_radius) / (outer_radius - inner_radius)))
color = (intensity, intensity, intensity)
# 绘制圆环
pygame.draw.circle(self.image, color, (center_x, center_y), r, 1)
# 添加旋转的高亮区域
highlight_angle = math.radians(pygame.time.get_ticks() / 10 % 360)
highlight_start = (center_x + inner_radius * math.cos(highlight_angle),
center_y + inner_radius * math.sin(highlight_angle))
highlight_end = (center_x + outer_radius * math.cos(highlight_angle),
center_y + outer_radius * math.sin(highlight_angle))
pygame.draw.line(self.image, (200, 200, 200), highlight_start, highlight_end, 2)
# 绘制中心黑洞(事件视界)
pygame.draw.circle(self.image, BLACK, (center_x, center_y), inner_radius)
# 添加引力透镜效果(扭曲背景)
for i in range(10):
angle = math.radians(i * 36)
dist = random.randint(inner_radius + 2, outer_radius - 2)
x = center_x + dist * math.cos(angle)
y = center_y + dist * math.sin(angle)
# 绘制被扭曲的"星光"
pygame.draw.line(self.image, (150, 150, 150),
(x, y),
(center_x + (dist - 2) * math.cos(angle),
center_y + (dist - 2) * math.sin(angle)),
1)
elif self.type == 'penetrate':
# 穿透 - 带光芒的五角星
# 绘制五角星
points = []
for i in range(5):
# 外顶点
outer_x = 15 + 10 * math.cos(math.radians(90 + i * 72))
outer_y = 15 + 10 * math.sin(math.radians(90 + i * 72))
points.append((outer_x, outer_y))
# 内顶点(旋转36度)
inner_x = 15 + 5 * math.cos(math.radians(90 + 36 + i * 72))
inner_y = 15 + 5 * math.sin(math.radians(90 + 36 + i * 72))
points.append((inner_x, inner_y))
pygame.draw.polygon(self.image, colors[self.type], points)
# 添加光芒效果
for i in range(8):
angle = math.radians(i * 45)
end_x = 15 + 15 * math.cos(angle)
end_y = 15 + 15 * math.sin(angle)
pygame.draw.line(self.image, (255, 255, 100), (15, 15), (end_x, end_y), 2)
elif self.type == 'tracking':
# 优化后的跟踪效果设计:雷达扫描+目标锁定
center_x, center_y = 20, 20
# 绘制雷达盘
pygame.draw.circle(self.image, (0, 200, 0), (center_x, center_y), 15, 2) # 外圈
pygame.draw.circle(self.image, (0, 150, 0), (center_x, center_y), 10, 1) # 内圈
# 添加网格线
pygame.draw.line(self.image, (0, 100, 0), (center_x - 15, center_y), (center_x + 15, center_y), 1)
pygame.draw.line(self.image, (0, 100, 0), (center_x, center_y - 15), (center_x, center_y + 15), 1)
pygame.draw.line(self.image, (0, 100, 0),
(center_x - 10, center_y - 10),
(center_x + 10, center_y + 10), 1)
pygame.draw.line(self.image, (0, 100, 0),
(center_x - 10, center_y + 10),
(center_x + 10, center_y - 10), 1)
# 动态扫描线
scan_angle = math.radians(pygame.time.get_ticks() / 10 % 360)
end_x = center_x + 15 * math.cos(scan_angle)
end_y = center_y + 15 * math.sin(scan_angle)
pygame.draw.line(self.image, (0, 255, 0), (center_x, center_y), (end_x, end_y), 2)
# 目标锁定指示器
lock_radius = 6
pygame.draw.circle(self.image, RED, (center_x, center_y), lock_radius, 2)
# 添加锁定动画
if (pygame.time.get_ticks() // 200) % 4 < 2:
# 绘制锁定框
pygame.draw.rect(self.image, RED, (center_x - lock_radius, center_y - lock_radius,
lock_radius * 2, lock_radius * 2), 2)
# 添加锁定角
corner_size = 4
# 左上角
pygame.draw.line(self.image, RED,
(center_x - lock_radius, center_y - lock_radius),
(center_x - lock_radius, center_y - lock_radius - corner_size), 2)
pygame.draw.line(self.image, RED,
(center_x - lock_radius, center_y - lock_radius),
(center_x - lock_radius - corner_size, center_y - lock_radius), 2)
# 右上角
pygame.draw.line(self.image, RED,
(center_x + lock_radius, center_y - lock_radius),
(center_x + lock_radius, center_y - lock_radius - corner_size), 2)
pygame.draw.line(self.image, RED,
(center_x + lock_radius, center_y - lock_radius),
(center_x + lock_radius + corner_size, center_y - lock_radius), 2)
# 左下角
pygame.draw.line(self.image, RED,
(center_x - lock_radius, center_y + lock_radius),
(center_x - lock_radius, center_y + lock_radius + corner_size), 2)
pygame.draw.line(self.image, RED,
(center_x - lock_radius, center_y + lock_radius),
(center_x - lock_radius - corner_size, center_y + lock_radius), 2)
# 右下角
pygame.draw.line(self.image, RED,
(center_x + lock_radius, center_y + lock_radius),
(center_x + lock_radius, center_y + lock_radius + corner_size), 2)
pygame.draw.line(self.image, RED,
(center_x + lock_radius, center_y + lock_radius),
(center_x + lock_radius + corner_size, center_y + lock_radius), 2)
elif self.type == 'silence':
# 优化后的沉默效果设计:消音器+静音符号
center_x, center_y = 20, 20
# 绘制消音器主体(枪管)
pygame.draw.rect(self.image, DARK_GRAY, (center_x - 15, center_y - 3, 30, 6))
# 绘制消音器筒体
for i in range(3):
pygame.draw.rect(self.image, (80, 80, 80),
(center_x - 10 + i * 7, center_y - 6, 5, 12))
# 绘制静音符号(带斜线的喇叭)
# 喇叭主体
pygame.draw.polygon(self.image, SILENCE_COLOR, [
(center_x, center_y), # 中心点
(center_x + 8, center_y - 6), # 右上
(center_x + 12, center_y - 6), # 右尖
(center_x + 12, center_y + 6), # 右下
(center_x + 8, center_y + 6), # 左下
])
# 斜线(静音符号)
pygame.draw.line(self.image, RED,
(center_x - 5, center_y - 8),
(center_x + 8, center_y + 7), 3)
# 添加动态"静音"波纹
now = pygame.time.get_ticks()
wave_phase = (now // 200) % 3
# 根据相位绘制不同大小的波纹
wave_radius = 8 + wave_phase * 3
pygame.draw.circle(self.image, (*SILENCE_COLOR, 100),
(center_x, center_y), wave_radius, 1)
# 添加振动抑制效果(点阵)
for i in range(10):
x = center_x + random.randint(-12, 12)
y = center_y + random.randint(-12, 12)
pygame.draw.circle(self.image, SILENCE_COLOR, (x, y), 1)
elif self.type == 'auto_fire':
# 新设计:旋转的齿轮+子弹图标,代表自动发射系统
center_x, center_y = 20, 20
# 绘制外部齿轮环
gear_radius = 15
tooth_count = 8
for i in range(tooth_count):
angle = math.radians(i * 360 / tooth_count)
# 齿轮齿
start_x = center_x + (gear_radius - 3) * math.cos(angle)
start_y = center_y + (gear_radius - 3) * math.sin(angle)
end_x = center_x + (gear_radius + 3) * math.cos(angle)
end_y = center_y + (gear_radius + 3) * math.sin(angle)
pygame.draw.line(self.image, AUTO_FIRE_COLOR, (start_x, start_y), (end_x, end_y), 3)
# 绘制内部旋转的子弹图标
rotation_angle = pygame.time.get_ticks() / 20 % 360 # 随时间旋转
rad = math.radians(rotation_angle)
# 子弹主体
bullet_length = 8
start_x = center_x
start_y = center_y
end_x = center_x + bullet_length * math.cos(rad)
end_y = center_y + bullet_length * math.sin(rad)
pygame.draw.line(self.image, YELLOW, (start_x, start_y), (end_x, end_y), 3)
# 子弹头部(三角形)
head_size = 5
head_points = [
(end_x, end_y),
(end_x + head_size * math.cos(rad + math.pi / 6),
end_y + head_size * math.sin(rad + math.pi / 6)),
(end_x + head_size * math.cos(rad - math.pi / 6),
end_y + head_size * math.sin(rad - math.pi / 6))
]
pygame.draw.polygon(self.image, ORANGE, head_points)
# 添加动态光效
if (pygame.time.get_ticks() // 200) % 2 == 0: # 闪烁效果
pygame.draw.circle(self.image, (255, 255, 255, 100),
(center_x, center_y), gear_radius + 2, 2)
elif self.type == 'vertical_fire':
# 垂直火力道具 - 深紫色垂直双箭头
center_x, center_y = 20, 20
# 绘制垂直双箭头
arrow_size = 10
# 上箭头
pygame.draw.polygon(self.image, VERTICAL_FIRE_COLOR, [
(center_x, center_y - arrow_size), # 顶点
(center_x - arrow_size // 2, center_y - arrow_size // 3), # 左下
(center_x - arrow_size // 4, center_y - arrow_size // 3), # 左中
(center_x - arrow_size // 4, center_y + arrow_size // 2), # 左下
(center_x + arrow_size // 4, center_y + arrow_size // 2), # 右下
(center_x + arrow_size // 4, center_y - arrow_size // 3), # 右中
(center_x + arrow_size // 2, center_y - arrow_size // 3) # 右下
])
# 下箭头
pygame.draw.polygon(self.image, VERTICAL_FIRE_COLOR, [
(center_x, center_y + arrow_size), # 底点
(center_x - arrow_size // 2, center_y + arrow_size // 3), # 左上
(center_x - arrow_size // 4, center_y + arrow_size // 3), # 左中
(center_x - arrow_size // 4, center_y - arrow_size // 2), # 左上
(center_x + arrow_size // 4, center_y - arrow_size // 2), # 右上
(center_x + arrow_size // 4, center_y + arrow_size // 3), # 右中
(center_x + arrow_size // 2, center_y + arrow_size // 3) # 右下
])
# 添加动态光效(垂直能量流)
now = pygame.time.get_ticks()
phase = (now // 100) % 3
for i in range(3):
y_offset = phase * 5 - 10 + i * 10
pygame.draw.line(self.image, (180, 50, 180),
(center_x, center_y - 15 + y_offset),
(center_x, center_y + 15 + y_offset), 3)
# 添加垂直火力标识
if (now // 200) % 2 == 0:
pygame.draw.line(self.image, (200, 100, 200),
(center_x, center_y - 12),
(center_x, center_y + 12), 2)
now = pygame.time.get_ticks()
arrow_y = center_y + math.sin(now / 200) * 8 # 上下移动的箭头
pygame.draw.polygon(self.image, (200, 100, 200), [
(center_x, arrow_y - 10), # 上箭头
(center_x - 5, arrow_y - 5),
(center_x + 5, arrow_y - 5)
])
pygame.draw.polygon(self.image, (200, 100, 200), [
(center_x, arrow_y + 10), # 下箭头
(center_x - 5, arrow_y + 5),
(center_x + 5, arrow_y + 5)
])
elif self.type == 'paralyze':
# 麻痹道具 - 锁链设计
center_x, center_y = 20, 20
# 绘制锁链环
chain_radius = 6
for i in range(3):
offset_x = 0
offset_y = i * 8 - 8
pygame.draw.circle(self.image, PARALYZE_COLOR,
(center_x + offset_x, center_y + offset_y), chain_radius, 2)
# 连接环
if i < 2:
pygame.draw.rect(self.image, PARALYZE_COLOR,
(center_x - 2, center_y + offset_y + chain_radius - 2,
4, 8))
# 添加锁图标
pygame.draw.rect(self.image, PARALYZE_COLOR, (center_x - 4, center_y - 12, 8, 6))
pygame.draw.arc(self.image, PARALYZE_COLOR, (center_x - 6, center_y - 10, 12, 8), 0, math.pi, 2)
# 添加动态效果(闪烁)
if (pygame.time.get_ticks() // 200) % 2 == 0:
pygame.draw.circle(self.image, (100, 180, 255),
(center_x, center_y), 10, 1)
elif self.type == 'split':
# 分裂射击道具 - 八芒星设计
center_x, center_y = 20, 20
# 绘制八芒星
points = []
for i in range(8):
# 外点(较长)
angle = math.radians(i * 45)
outer_radius = 15
points.append((
center_x + outer_radius * math.cos(angle),
center_y + outer_radius * math.sin(angle)
))
# 内点(较短)
angle = math.radians(i * 45 + 22.5)
inner_radius = 7
points.append((
center_x + inner_radius * math.cos(angle),
center_y + inner_radius * math.sin(angle)
))
pygame.draw.polygon(self.image, SPLIT_COLOR, points)
# 添加中心点和动态效果
pygame.draw.circle(self.image, YELLOW, (center_x, center_y), 4)
# 添加旋转的子弹图标
rotation_angle = pygame.time.get_ticks() / 20 % 360
rad = math.radians(rotation_angle)
end_x = center_x + 10 * math.cos(rad)
end_y = center_y + 10 * math.sin(rad)
pygame.draw.line(self.image, YELLOW, (center_x, center_y), (end_x, end_y), 2)
# 添加发光效果
if (pygame.time.get_ticks() // 200) % 2 == 0:
pygame.draw.circle(self.image, (255, 200, 0, 100),
(center_x, center_y), 18, 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 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()
powerups = 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
paused = 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)
# 主游戏循环
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
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)
elif powerup.type == 'penetrate':
player.penetrate_active = True
player.penetrate_timer = pygame.time.get_ticks() + 10000 # 持续10秒
player.powerup_text = "子弹穿透激活!"
player.text_timer = pygame.time.get_ticks()
# 设置一个事件来结束穿透状态
pygame.time.set_timer(pygame.USEREVENT + 9, 10000)
elif powerup.type == 'tracking':
player.tracking_active = True
player.tracking_timer = pygame.time.get_ticks() + 10000 # 持续10秒
player.powerup_text = "子弹跟踪激活!"
player.text_timer = pygame.time.get_ticks()
# 设置结束事件
pygame.time.set_timer(pygame.USEREVENT + 10, 10000)
elif powerup.type == 'silence':
# 检查是否处于麻痹状态,如果麻痹则不触发沉默
if not player.paralyzed:
player.silenced = True
player.silence_timer = pygame.time.get_ticks() + 5000 # 沉默5秒
player.powerup_text = "沉默状态!无法射击!"
player.text_timer = pygame.time.get_ticks()
# 设置结束事件
pygame.time.set_timer(pygame.USEREVENT + 11, 5000)
else:
# 添加提示说明被麻痹时无法沉默
player.powerup_text = "麻痹中无法沉默!"
player.text_timer = pygame.time.get_ticks()
elif powerup.type == 'auto_fire':
player.auto_fire = True
player.auto_fire_timer = 30 * 60 # 持续30秒(60帧/秒)
player.powerup_text = "自动发射激活!"
player.text_timer = pygame.time.get_ticks()
# 设置自动发射结束事件
pygame.time.set_timer(pygame.USEREVENT + 12, 30000) # 30秒后失效
elif powerup.type == 'vertical_fire':
player.vertical_fire = True
player.vertical_fire_timer = pygame.time.get_ticks() + 8000 # 持续8秒
player.powerup_text = "垂直火力激活!"
player.text_timer = pygame.time.get_ticks()
# 设置结束事件
pygame.time.set_timer(pygame.USEREVENT + 13, 8000)
elif powerup.type == 'paralyze':
# 不能与沉默道具同时生效
if not player.silenced:
player.paralyzed = True
player.paralyze_timer = pygame.time.get_ticks() + 5000 # 麻痹5秒
player.powerup_text = "麻痹状态!无法移动!"
player.text_timer = pygame.time.get_ticks()
# 设置结束事件
pygame.time.set_timer(pygame.USEREVENT + 14, 5000)
else:
# 添加提示说明沉默中无法麻痹
player.powerup_text = "沉默中无法麻痹!"
player.text_timer = pygame.time.get_ticks()
elif powerup.type == 'split':
player.split_active = True
player.split_timer = pygame.time.get_ticks() + 8000 # 持续8秒
player.powerup_text = "分裂射击激活!"
player.text_timer = pygame.time.get_ticks()
# 设置结束事件
pygame.time.set_timer(pygame.USEREVENT + 15, 8000)
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)
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 新增ESC键暂停/继续功能
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = not paused # 切换暂停状态
if event.type == pygame.USEREVENT + 15:
player.split_active = False
player.powerup_text = "分裂射击结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 15, 0)
if event.type == pygame.USEREVENT + 14:
player.paralyzed = False
player.powerup_text = "麻痹状态结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 14, 0)
if event.type == pygame.USEREVENT + 13:
player.vertical_fire = False
player.powerup_text = "垂直火力结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 13, 0) # 关闭计时器
if event.type == pygame.USEREVENT + 12:
player.auto_fire = False
player.powerup_text = "自动发射结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 12, 0) # 关闭计时器
if event.type == pygame.USEREVENT + 11:
player.silenced = False
player.powerup_text = "沉默状态结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 11, 0) # 关闭计时器
if event.type == pygame.USEREVENT + 10:
player.tracking_active = False
player.powerup_text = "跟踪效果结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 10, 0) # 关闭计时器
if event.type == pygame.USEREVENT + 9:
player.penetrate_active = False
player.powerup_text = "穿透效果结束"
player.text_timer = pygame.time.get_ticks()
pygame.time.set_timer(pygame.USEREVENT + 9, 0) # 关闭计时器
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
# 恢复原始颜色
colored_surface = pygame.Surface(enemy.image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(colored_surface, enemy.original_color, enemy.scaled_shape)
enemy.image.blit(colored_surface, (0, 0))
# 添加解除特效
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 and not paused:
now = pygame.time.get_ticks()
if player.auto_fire and now - player.last_auto_shot > 200:
player.shoot()
player.last_auto_shot = now
# 游戏逻辑
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, False) # 不立即删除子弹
for enemy, bullet_list in hits.items():
score += 50
explosion = Explosion(enemy.rect.center)
all_sprites.add(explosion)
explosions.add(explosion)
# 分裂射击效果
if player.split_active:
# 向8个方向发射子弹
angles = [0, 45, 90, 135, 180, 225, 270, 315]
for angle in angles:
rad = math.radians(angle)
speedx = math.cos(rad) * 5
speedy = math.sin(rad) * 5
# 创建普通子弹(无特殊效果)
split_bullet = Bullet(
enemy.rect.centerx,
enemy.rect.centery,
speedx=speedx,
speedy=speedy
)
split_bullet.image.fill(YELLOW) # 普通黄色子弹
all_sprites.add(split_bullet)
bullets.add(split_bullet)
# 道具掉落逻辑
if random.random() < 0.5:
powerup = PowerUp(enemy.rect.center)
all_sprites.add(powerup)
powerups.add(powerup)
# 处理子弹穿透
for bullet in bullet_list:
if bullet.penetrate:
bullet.penetrate_count += 1
if bullet.penetrate_count >= 3:
bullet.kill()
else:
bullet.kill() # 非穿透子弹立即删除
for bullet in bullets.sprites()[:]: # 获取精灵列表后再切片
hit_enemies = pygame.sprite.spritecollide(bullet, enemies, True)
if hit_enemies:
for enemy in hit_enemies:
score += 50
explosion = Explosion(enemy.rect.center)
all_sprites.add(explosion)
explosions.add(explosion)
# 道具掉落(80%概率)
if random.random() < 0.8:
powerup = PowerUp(enemy.rect.center)
all_sprites.add(powerup)
powerups.add(powerup)
# 处理子弹:非穿透子弹击中后消失,穿透子弹则继续存在
if not bullet.penetrate:
bullet.kill()
else:
# 增加穿透计数(可选:限制最大穿透次数)
bullet.penetrate_count += 1
if bullet.penetrate_count >= 3: # 最多穿透3个敌机
bullet.kill()
# 检测道具拾取
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)
# 绘制其他元素
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)
# 自动发射状态指示器 ↓
if player.auto_fire:
remaining_time = player.auto_fire_timer // 60
auto_text = font.render(f"AUTO FIRE: {remaining_time}s", True, AUTO_FIRE_COLOR)
screen.blit(auto_text, (10, 90)) # 显示在屏幕左上角
# 添加道具提示文字(在游戏结束界面之前)
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)
# 在绘制其他信息之后,游戏结束界面之前添加暂停提示
if paused:
# 创建半透明覆盖层
overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 128)) # 半透明黑色
screen.blit(overlay, (0, 0))
# 绘制暂停文字
pause_font = pygame.font.Font(font_path, 72)
pause_text = pause_font.render("暂停中", True, YELLOW)
pause_rect = pause_text.get_rect(center=(WIDTH // 2, HEIGHT // 2))
screen.blit(pause_text, pause_rect)
# 绘制提示文字
hint_font = pygame.font.Font(font_path, 24)
hint_text = hint_font.render("按ESC键继续", True, WHITE)
hint_rect = hint_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 + 60))
screen.blit(hint_text, hint_rect)
pygame.display.flip()
pygame.quit()