import pygameimport mathimport randomimport sys# ================= 基础配置 =================pygame.init()WIDTH = 1000HEIGHT = 750screen = pygame.display.set_mode((WIDTH, HEIGHT))pygame.display.set_caption("🎆 浪漫烟花爱心 🎆")clock = pygame.time.Clock()FPS = 60# 颜色系统BLACK = (0, 0, 0)HEART_MAIN = (255, 0, 100)HEART_GLOW = (255, 120, 200)TRAIL_COLOR = (255, 150, 210)# ================= 文字配置(可自定义) =================TEXT_CONTENT = "LOVE" # 可替换为「我爱你」「520」等FONT_SIZE = 72# 兼容全系统字体加载try: FONT = pygame.font.SysFont("SimHei", FONT_SIZE)except: FONT = pygame.font.Font(None, FONT_SIZE)# 预渲染文字,保证居中TEXT_SURFACE = FONT.render(TEXT_CONTENT, True, (255, 255, 255))TEXT_RECT = TEXT_SURFACE.get_rect(center=(WIDTH//2, HEIGHT//2 + 60))# ================= 爱心数学工具(预生成完整轮廓) =================HEART_POINTS = []HEART_SCALE = 22HEART_CENTER = (WIDTH//2, HEIGHT//2 - 30)# 预生成1000个均匀分布的爱心轮廓点,保证形状完整无缺口for t in range(0, 1000): t = t / 1000 * 2 * math.pi x = 16 * math.sin(t) ** 3 y = -(13 * math.cos(t) - 5 * math.cos(2*t) - 2 * math.cos(3*t) - math.cos(4*t)) HEART_POINTS.append(( HEART_CENTER[0] + x * HEART_SCALE, HEART_CENTER[1] + y * HEART_SCALE ))# 生成爱心内部填充点(保证实心饱满)FILL_POINTS = []for _ in range(1500): t = random.uniform(0, 2 * math.pi) scale = random.uniform(0, HEART_SCALE * 0.9) x = 16 * math.sin(t) ** 3 y = -(13 * math.cos(t) - 5 * math.cos(2*t) - 2 * math.cos(3*t) - math.cos(4*t)) FILL_POINTS.append(( HEART_CENTER[0] + x * scale, HEART_CENTER[1] + y * scale ))# ================= 粒子类(核心逻辑) =================class Particle: def __init__(self, is_fill=False): self.is_fill = is_fill self.reset() def reset(self): if not self.is_fill: # 轮廓粒子:从底部发射,精准飞向爱心轮廓 self.x = random.uniform(WIDTH * 0.2, WIDTH * 0.8) self.y = HEIGHT + random.uniform(20, 80) self.vx = random.uniform(-0.8, 0.8) self.vy = random.uniform(-16, -12) self.gravity = 0.13 self.target_idx = random.randint(0, len(HEART_POINTS)-1) self.tx, self.ty = HEART_POINTS[self.target_idx] self.size = random.uniform(3, 5.5) self.alpha = 255 self.state = 0 # 0=升空 1=凝聚 self.timer = 0 self.phase = random.uniform(0, 2 * math.pi) self.trail = [] else: # 填充粒子:直接生成在爱心内部,保证实心饱满 idx = random.randint(0, len(FILL_POINTS)-1) self.x, self.y = FILL_POINTS[idx] self.size = random.uniform(1.5, 3.5) self.alpha = random.randint(180, 255) self.phase = random.uniform(0, 2 * math.pi) self.state = 1 def update(self): if self.is_fill: # 填充粒子:仅做轻微呼吸,保持爱心实心 self.phase += 0.05 self.alpha = int(180 + 75 * math.sin(self.phase)) self.x += math.sin(self.phase) * 0.2 self.y += math.cos(self.phase) * 0.2 return # 轮廓粒子状态机 if self.state == 0: # 阶段1:升空(精准飞向目标点) self.vy += self.gravity self.x += self.vx self.y += self.vy self.trail.append((self.x, self.y)) if len(self.trail) > 15: self.trail.pop(0) dist = math.hypot(self.x - self.tx, self.y - self.ty) if dist < 25: self.state = 1 self.vx = 0 self.vy = 0 self.trail.clear() else: # 阶段2:凝聚(轻微浮动,保持轮廓完整) self.timer += 1 self.phase += 0.06 swing = math.sin(self.phase) * 1.2 self.x = self.tx + swing self.y = self.ty + swing * 0.6 self.alpha = int(200 + 55 * math.sin(self.phase)) if self.timer > 180: self.reset() def draw(self, surface): if self.is_fill: # 绘制填充粒子 color = (*HEART_MAIN, self.alpha) pygame.draw.circle(surface, color, (int(self.x), int(self.y)), int(self.size)) return # 绘制轮廓粒子拖尾 if len(self.trail) > 0: for i, (px, py) in enumerate(self.trail): a = int(120 * (i / len(self.trail))) color = (*TRAIL_COLOR, a) pygame.draw.circle(surface, color, (int(px), int(py)), int(self.size * 0.4)) # 绘制轮廓粒子本体 color = (*HEART_MAIN, self.alpha) s = pygame.Surface((int(self.size*2), int(self.size*2)), pygame.SRCALPHA) pygame.draw.circle(s, color, (int(self.size), int(self.size)), int(self.size)) surface.blit(s, (int(self.x - self.size), int(self.y - self.size))) # 绘制光晕(仅凝聚状态显示) if self.state == 1: glow_a = int(60 + 30 * math.sin(self.phase)) glow = pygame.Surface((int(self.size*6), int(self.size*6)), pygame.SRCALPHA) glow_color = (*HEART_GLOW, glow_a) pygame.draw.circle(glow, glow_color, (int(self.size*3), int(self.size*3)), int(self.size*3)) surface.blit(glow, (int(self.x - self.size*3), int(self.y - self.size*3)))# ================= 主程序 =================outline_particles = [Particle(is_fill=False) for _ in range(800)]fill_particles = [Particle(is_fill=True) for _ in range(1500)]running = Truewhile running: clock.tick(FPS) screen.fill(BLACK) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: running = False # 分层渲染:填充层 → 轮廓层 → 文字层 for p in fill_particles: p.update() p.draw(screen) for p in outline_particles: p.update() p.draw(screen) # 绘制文字(最上层,不被遮挡) time = pygame.time.get_ticks() * 0.001 text_alpha = int(200 + 55 * math.sin(time)) text_surf = TEXT_SURFACE.copy() text_surf.set_alpha(text_alpha) screen.blit(text_surf, TEXT_RECT) pygame.display.flip()pygame.quit()sys.exit()