Python 画绚烂浪漫的烟花效果
·
这篇文章介绍了一个使用Pygame库实现的多种类型烟花模拟程序。程序实现了四种不同形状的烟花效果:圆形爆炸、星形爆炸、螺旋爆炸和心形爆炸。每个烟花由多个粒子组成,通过不同的参数方程控制粒子运动轨迹形成特定图案。程序提供了实时交互功能,用户可以通过空格键添加新烟花组,系统也会随机生成烟花。视觉效果方面,实现了粒子淡出和尾迹效果,增强了真实感。这个模拟展示了如何使用数学函数控制粒子行为来创造多样的视觉效果。

import pygame
import random
import math
import sys
# 初始化pygame
pygame.init()
# 设置窗口尺寸
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("绚烂烟花模拟 - 多种类型烟花展示")
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
COLORS = [
(255, 0, 0), (0, 255, 0), (0, 0, 255),
(255, 255, 0), (255, 0, 255), (0, 255, 255),
(255, 165, 0), (255, 192, 203), (138, 43, 226)
]
# 烟花粒子类
class Particle:
def __init__(self, x, y, color, velocity_x, velocity_y, size=2, decay=0.97, gravity=0.15):
self.x = x
self.y = y
self.color = color
self.velocity_x = velocity_x
self.velocity_y = velocity_y
self.size = size
self.decay = decay
self.gravity = gravity
self.lifetime = 255
def update(self):
self.velocity_x *= self.decay
self.velocity_y *= self.decay
self.velocity_y += self.gravity
self.x += self.velocity_x
self.y += self.velocity_y
self.lifetime -= 4
def draw(self, surface):
if self.lifetime > 0:
alpha = min(self.lifetime, 255)
color_with_alpha = (self.color[0], self.color[1], self.color[2], alpha)
surf = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA)
pygame.draw.circle(surf, color_with_alpha, (self.size, self.size), self.size)
surface.blit(surf, (int(self.x - self.size), int(self.y - self.size)))
def is_dead(self):
return self.lifetime <= 0
# 烟花类
class Firework:
def __init__(self, x, y, type_index):
self.x = x
self.y = y
self.type_index = type_index
self.color = random.choice(COLORS)
self.particles = []
self.exploded = False
self.velocity_y = -random.uniform(8, 12)
self.gravity = 0.2
# 根据类型索引决定烟花类型
self.type = type_index % 4 # 0:圆形, 1:星形, 2:螺旋, 3:心形
def update(self):
if not self.exploded:
self.velocity_y += self.gravity
self.y += self.velocity_y
# 当速度变为正数(开始下落)时爆炸
if self.velocity_y >= 0:
self.explode()
else:
# 更新所有粒子
for particle in self.particles[:]:
particle.update()
if particle.is_dead():
self.particles.remove(particle)
def draw(self, surface):
if not self.exploded:
# 绘制上升的烟花
pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), 3)
# 绘制尾迹
for i in range(5):
pos_y = self.y + i * 3
alpha = 255 - i * 50
if alpha > 0:
trail_color = (self.color[0], self.color[1], self.color[2], alpha)
surf = pygame.Surface((6, 6), pygame.SRCALPHA)
pygame.draw.circle(surf, trail_color, (3, 3), 2)
surface.blit(surf, (int(self.x - 3), int(pos_y - 3)))
else:
# 绘制所有粒子
for particle in self.particles:
particle.draw(surface)
def explode(self):
self.exploded = True
num_particles = 0
# 根据烟花类型生成不同的粒子模式
if self.type == 0: # 圆形爆炸
num_particles = 150
for _ in range(num_particles):
angle = random.uniform(0, math.pi * 2)
speed = random.uniform(2, 6)
velocity_x = math.cos(angle) * speed
velocity_y = math.sin(angle) * speed
self.particles.append(Particle(self.x, self.y, self.color, velocity_x, velocity_y))
elif self.type == 1: # 星形爆炸
num_particles = 200
points = 5 # 五角星
for i in range(num_particles):
angle = (i % points) * (2 * math.pi / points) + random.uniform(-0.2, 0.2)
speed = random.uniform(3, 7)
velocity_x = math.cos(angle) * speed
velocity_y = math.sin(angle) * speed
self.particles.append(Particle(self.x, self.y, self.color, velocity_x, velocity_y))
elif self.type == 2: # 螺旋形爆炸
num_particles = 250
for i in range(num_particles):
angle = i * 0.1
radius = i * 0.05
speed = random.uniform(2, 5)
velocity_x = math.cos(angle) * radius * speed
velocity_y = math.sin(angle) * radius * speed
self.particles.append(Particle(self.x, self.y, self.color, velocity_x, velocity_y))
elif self.type == 3: # 心形爆炸
num_particles = 180
for i in range(num_particles):
t = i / num_particles * 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)
# 缩放和随机化
scale = random.uniform(0.2, 0.4)
velocity_x = x * scale
velocity_y = -y * scale # 反转y轴使心形正立
self.particles.append(Particle(self.x, self.y, self.color, velocity_x, velocity_y))
def is_dead(self):
return self.exploded and len(self.particles) == 0
# 主循环
def main():
clock = pygame.time.Clock()
fireworks = []
running = True
# 创建半透明的surface用于实现淡出效果
fade_surface = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
fade_surface.fill((0, 0, 0, 25)) # 黑色带透明度
# 初始化一些烟花
for i in range(4):
fireworks.append(Firework(random.randint(100, WIDTH-100), HEIGHT, i))
# 显示说明文字
font = pygame.font.SysFont('simhei', 24)
text1 = font.render("圆形爆炸 星形爆炸 螺旋爆炸 心形爆炸", True, WHITE)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_SPACE:
# 空格键添加一组新烟花
for i in range(4):
fireworks.append(Firework(random.randint(100, WIDTH-100), HEIGHT, i))
# 应用淡出效果
screen.blit(fade_surface, (0, 0))
# 随机添加新烟花
if random.random() < 0.05 and len(fireworks) < 20:
fireworks.append(Firework(random.randint(100, WIDTH-100), HEIGHT, random.randint(0, 3)))
# 更新和绘制所有烟花
for firework in fireworks[:]:
firework.update()
firework.draw(screen)
if firework.is_dead():
fireworks.remove(firework)
# 显示说明文字
screen.blit(text1, (WIDTH//2 - text1.get_width()//2, 20))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
更多推荐
所有评论(0)