前言
有了前面的基础想对“外星人入侵”这游戏进行修改,去除导入图片的部分,直接使用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()
总结
各位大佬如果有什么好的想法可以在评论区留言,整体来说还是非常消耗时间的。