绚丽烟花秀(Python)

绚丽烟花秀(Python)_第1张图片

这是一个使用PyQt5框架创建图形界面的烟花秀程序,采用面向对象设计,包含三个主要类:Particle(粒子)、Firework(烟花)和FireworkWindow(主窗口)。鼠标点击创建烟花,自动随机生成烟花(每600ms),采用粒子运动物理模拟(重力、阻力),并有粒子轨迹效果(带透明度渐变),实现烟花粒子的生命周期管理。

Particle类(粒子)

  • 负责单个粒子的运动和渲染
  • 包含位置、速度、颜色、生命周期等属性
  • 实现粒子的运动物理(重力、阻力)和轨迹效果
class Particle:
    def __init__(self, x, y):
        # 初始化粒子位置、速度、颜色等属性
        self.x = x
        self.y = y
        self.angle = random.uniform(0, 2 * math.pi)  # 随机运动方向
        self.velocity = random.uniform(3, 12)        # 随机速度
 # 粒子颜色 - 使用RGB值创建更鲜艳的颜色
        bright_colors = [
            (255, 0, 0),      # 红
            (0, 255, 0),      # 绿
            (0, 0, 255),      # 蓝
            (255, 255, 0),    # 黄
            (255, 0, 255),    # 紫
            (0, 255, 255),    # 青
            (255, 165, 0),    # 橙
            (255, 255, 255),  # 白
        ]
        color = random.choice(bright_colors)
        self.color = QColor(*color)
        self.life = 100                             # 生命周期
        self.trail = [QPoint(int(x), int(y))]      # 粒子轨迹
def update(self):
        """更新粒子位置和状态"""
        # 应用重力和阻力
        self.velocity *= 0.97
        dx = math.cos(self.angle) * self.velocity
        dy = math.sin(self.angle) * self.velocity + 0.15  # 轻微重力
        
        # 更新位置
        self.x += dx
        self.y += dy
        
        # 添加到轨迹
        self.trail.append(QPoint(int(self.x), int(self.y)))
        if len(self.trail) > self.max_trail_length:
            self.trail.pop(0)
        
        # 减少生命值
        self.life -= 1.5
        
        # 返回粒子是否还活着
        return self.life > 0

    def draw(self, painter):
        """绘制粒子"""
        # 设置颜色和透明度
        color = QColor(self.color)
        color.setAlpha(int(self.life * 2.5))  # 增加亮度
        
        # 绘制轨迹
        if len(self.trail) > 1:
            for i in range(len(self.trail) - 1):
                # 轨迹渐变效果
                alpha = int((i / len(self.trail)) * self.life * 2)
                trail_color = QColor(self.color)
                trail_color.setAlpha(alpha)
                
                pen = QPen(trail_color, 2)  # 增加线宽
                painter.setPen(pen)
                painter.drawLine(self.trail[i], self.trail[i + 1])
        
        # 绘制粒子
        painter.setPen(Qt.NoPen)
        painter.setBrush(QBrush(color))
        painter.drawEllipse(int(self.x - self.size/2), 
                          int(self.y - self.size/2), 
                          self.size, self.size)

Firework类(烟花)

  • 管理一组粒子形成烟花效果
  • 控制粒子的创建和更新
  • 处理整体烟花的生命周期
class Firework:
    """烟花类"""
    def __init__(self, x, y):
        self.particles = []
        # 创建多个粒子
        for _ in range(150):  # 增加粒子数量
            self.particles.append(Particle(x, y))
        print(f"创建烟花 at ({x}, {y}) 包含 {len(self.particles)} 个粒子")

    def update(self):
        """更新所有粒子"""
        # 过滤掉已经消失的粒子
        old_count = len(self.particles)
        self.particles = [p for p in self.particles if p.update()]
        new_count = len(self.particles)
        
        if old_count > 0 and new_count == 0:
            print("烟花消失")
        
        return new_count > 0  # 如果还有粒子存活,返回True

    def draw(self, painter):
        """绘制所有粒子"""
        for particle in self.particles:
            particle.draw(painter)

FireworkWindow类(主窗口)

  • 创建和管理主窗口
  • 处理用户输入(鼠标点击)
  • 控制动画循环和自动生成烟花
class FireworkWindow(QMainWindow):
    """烟花窗口类"""
    def __init__(self):
        super().__init__()
        print("初始化烟花窗口")
        self.initUI()
        
    def initUI(self):
        """初始化UI"""
        # 设置窗口
        self.setWindowTitle('绚丽烟花秀')
        
        # 居中显示
        self.center()
        
        # 设置窗口大小
        self.resize(1000, 800)  # 增加窗口大小
        
        # 设置黑色背景
        self.setStyleSheet("background-color: black;")
        
        # 烟花列表
        self.fireworks = []
        
        # 设置定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateFireworks)
        self.timer.start(16)  # 约60FPS
        
        # 自动生成烟花的定时器
        self.auto_timer = QTimer(self)
        self.auto_timer.timeout.connect(self.createRandomFirework)
        self.auto_timer.start(600)  # 每600毫秒生成一个随机烟花
        
        # 显示窗口
        self.show()
        self.raise_()  # 将窗口提升到前台
        self.activateWindow()  # 激活窗口
        
        print(f"窗口大小: {self.width()}x{self.height()}")
        print("窗口已显示")
        
        # 创建初始烟花
        self.createRandomFirework()
    
    def center(self):
        """将窗口居中显示"""
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        print(f"窗口居中位置: {qr.topLeft().x()}, {qr.topLeft().y()}")
    
    def createRandomFirework(self):
        """在随机位置创建烟花"""
        x = random.randint(100, self.width() - 100)
        y = random.randint(100, self.height() - 100)
        self.fireworks.append(Firework(x, y))
    
    def updateFireworks(self):
        """更新所有烟花"""
        # 更新并过滤掉已经消失的烟花
        old_count = len(self.fireworks)
        self.fireworks = [fw for fw in self.fireworks if fw.update()]
        new_count = len(self.fireworks)
        
        if old_count != new_count:
            print(f"当前烟花数量: {new_count}")
        
        # 重绘窗口
        self.update()
    
    def mousePressEvent(self, event):
        """鼠标点击事件处理"""
        if event.button() == Qt.LeftButton:
            # 在鼠标点击位置创建烟花
            self.fireworks.append(Firework(event.x(), event.y()))
            print(f"鼠标点击创建烟花 at ({event.x()}, {event.y()})")
    
    def paintEvent(self, event):
        """绘制事件处理"""
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 绘制所有烟花
        for firework in self.fireworks:
            firework.draw(painter)

def main():
    """主函数"""
    print("启动烟花程序")
    app = QApplication(sys.argv)
    window = FireworkWindow()
    print("进入应用主循环")
    sys.exit(app.exec_())

完整代码如下:

import sys
import random
import math
from PyQt5.QtWidgets import QApplication, QMainWindow, QDesktopWidget
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush
from PyQt5.QtCore import Qt, QTimer, QPoint

class Particle:
    """烟花粒子类"""
    def __init__(self, x, y):
        # 粒子初始位置
        self.x = x
        self.y = y
        
        # 随机角度和速度
        self.angle = random.uniform(0, 2 * math.pi)
        self.velocity = random.uniform(3, 12)  # 增加速度范围
        
        # 粒子颜色 - 使用RGB值创建更鲜艳的颜色
        bright_colors = [
            (255, 0, 0),      # 红
            (0, 255, 0),      # 绿
            (0, 0, 255),      # 蓝
            (255, 255, 0),    # 黄
            (255, 0, 255),    # 紫
            (0, 255, 255),    # 青
            (255, 165, 0),    # 橙
            (255, 255, 255),  # 白
        ]
        color = random.choice(bright_colors)
        self.color = QColor(*color)
        
        # 粒子生命周期和大小
        self.life = 100
        self.size = random.randint(3, 8)  # 增加粒子大小
        
        # 存储粒子轨迹
        self.trail = [QPoint(int(x), int(y))]
        self.max_trail_length = 8  # 增加轨迹长度

    def update(self):
        """更新粒子位置和状态"""
        # 应用重力和阻力
        self.velocity *= 0.97
        dx = math.cos(self.angle) * self.velocity
        dy = math.sin(self.angle) * self.velocity + 0.15  # 轻微重力
        
        # 更新位置
        self.x += dx
        self.y += dy
        
        # 添加到轨迹
        self.trail.append(QPoint(int(self.x), int(self.y)))
        if len(self.trail) > self.max_trail_length:
            self.trail.pop(0)
        
        # 减少生命值
        self.life -= 1.5
        
        # 返回粒子是否还活着
        return self.life > 0

    def draw(self, painter):
        """绘制粒子"""
        # 设置颜色和透明度
        color = QColor(self.color)
        color.setAlpha(int(self.life * 2.5))  # 增加亮度
        
        # 绘制轨迹
        if len(self.trail) > 1:
            for i in range(len(self.trail) - 1):
                # 轨迹渐变效果
                alpha = int((i / len(self.trail)) * self.life * 2)
                trail_color = QColor(self.color)
                trail_color.setAlpha(alpha)
                
                pen = QPen(trail_color, 2)  # 增加线宽
                painter.setPen(pen)
                painter.drawLine(self.trail[i], self.trail[i + 1])
        
        # 绘制粒子
        painter.setPen(Qt.NoPen)
        painter.setBrush(QBrush(color))
        painter.drawEllipse(int(self.x - self.size/2), 
                          int(self.y - self.size/2), 
                          self.size, self.size)

class Firework:
    """烟花类"""
    def __init__(self, x, y):
        self.particles = []
        # 创建多个粒子
        for _ in range(150):  # 增加粒子数量
            self.particles.append(Particle(x, y))
        print(f"创建烟花 at ({x}, {y}) 包含 {len(self.particles)} 个粒子")

    def update(self):
        """更新所有粒子"""
        # 过滤掉已经消失的粒子
        old_count = len(self.particles)
        self.particles = [p for p in self.particles if p.update()]
        new_count = len(self.particles)
        
        if old_count > 0 and new_count == 0:
            print("烟花消失")
        
        return new_count > 0  # 如果还有粒子存活,返回True

    def draw(self, painter):
        """绘制所有粒子"""
        for particle in self.particles:
            particle.draw(painter)

class FireworkWindow(QMainWindow):
    """烟花窗口类"""
    def __init__(self):
        super().__init__()
        print("初始化烟花窗口")
        self.initUI()
        
    def initUI(self):
        """初始化UI"""
        # 设置窗口
        self.setWindowTitle('绚丽烟花秀')
        
        # 居中显示
        self.center()
        
        # 设置窗口大小
        self.resize(1000, 800)  # 增加窗口大小
        
        # 设置黑色背景
        self.setStyleSheet("background-color: black;")
        
        # 烟花列表
        self.fireworks = []
        
        # 设置定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateFireworks)
        self.timer.start(16)  # 约60FPS
        
        # 自动生成烟花的定时器
        self.auto_timer = QTimer(self)
        self.auto_timer.timeout.connect(self.createRandomFirework)
        self.auto_timer.start(600)  # 每600毫秒生成一个随机烟花
        
        # 显示窗口
        self.show()
        self.raise_()  # 将窗口提升到前台
        self.activateWindow()  # 激活窗口
        
        print(f"窗口大小: {self.width()}x{self.height()}")
        print("窗口已显示")
        
        # 创建初始烟花
        self.createRandomFirework()
    
    def center(self):
        """将窗口居中显示"""
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        print(f"窗口居中位置: {qr.topLeft().x()}, {qr.topLeft().y()}")
    
    def createRandomFirework(self):
        """在随机位置创建烟花"""
        x = random.randint(100, self.width() - 100)
        y = random.randint(100, self.height() - 100)
        self.fireworks.append(Firework(x, y))
    
    def updateFireworks(self):
        """更新所有烟花"""
        # 更新并过滤掉已经消失的烟花
        old_count = len(self.fireworks)
        self.fireworks = [fw for fw in self.fireworks if fw.update()]
        new_count = len(self.fireworks)
        
        if old_count != new_count:
            print(f"当前烟花数量: {new_count}")
        
        # 重绘窗口
        self.update()
    
    def mousePressEvent(self, event):
        """鼠标点击事件处理"""
        if event.button() == Qt.LeftButton:
            # 在鼠标点击位置创建烟花
            self.fireworks.append(Firework(event.x(), event.y()))
            print(f"鼠标点击创建烟花 at ({event.x()}, {event.y()})")
    
    def paintEvent(self, event):
        """绘制事件处理"""
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        
        # 绘制所有烟花
        for firework in self.fireworks:
            firework.draw(painter)

def main():
    """主函数"""
    print("启动烟花程序")
    app = QApplication(sys.argv)
    window = FireworkWindow()
    print("进入应用主循环")
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

你可能感兴趣的:(python,python,开发语言)