求解,报错了

本文介绍了一个使用Python的Tkinter库创建的动态烟花动画,通过粒子系统模拟烟花绽放过程,包括随机位置、颜色和速度。烟花粒子随时间变化,遵循特定轨迹并有生命周期,最终在画布上展示出绚丽的效果。

import tkinter as tk
from fileinput import close
from logging import root

import ignite
from PIL import Image, ImageTk
from time import time, sleep
from random import choice, uniform, randint
from math import sin, cos, radians

colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen']




class Firework:
    # 属性:
    # - id:粒子的id
    # -x,y:粒子的坐标
    # - vx, vy:在坐标的变化速度
    # - total:总数
    # - age:粒子存在的时长
    # - color:颜色
    # - cv:画布
    # - lifespan:最高存在时长
    def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx=0., vy=0., size=10, color='red', lifespan=50):
        self.id = idx
        # 烟花绽放x轴
        self.x = x
        # 烟花绽放y轴
        self.y = y
        self.initial_speed = explosion_speed
        # 外放x轴速度
        self.vx = vx
        # 外放y轴速度
        self.vy = vy
        # 绽放的粒子数
        self.total = total
        # 已停留时间
        self.age = 0
        # 颜色
        self.color = color
        # 画布
        self.cv = cv
        self.cid = self.cv.create_oval(x - size, y - size, x + size, y + size, fill=self.color)
        self.lifespan = lifespan

    def update(self, dt):
        # 更新粒子年龄
        self.age += dt

        # 如果粒子仍然存活且可以膨胀
        if self.alive() and self.expand():
            # 计算粒子在x轴和y轴上的移动距离
            move_x = cos(radians(self.id * 360 / self.total)) * self.initial_speed
            move_y = -sin(radians(self.id * 360 / self.total)) * self.initial_speed

            # 更新粒子的位置
            self.cv.move(self.cid, move_x, move_y)

            # 更新粒子的速度
            self.vx = move_x / (float(dt) * 1000)

        # 如果粒子仍然存活且未达到最大下落速度
        elif self.alive():
            # 计算粒子在x轴上的移动距离
            move_x = cos(radians(self.id * 360 / self.total))

            # 更新粒子的位置
            self.cv.move(self.cid, self.vx + move_x, self.vy + 0.5 * dt)

            # 更新粒子的速度
            self.vy += 0.5 * dt

        # 如果粒子的生命周期已过,将其移除
        elif self.cid is not None:
            self.cv.delete(self.cid)
            self.cid = None

    # 定义膨胀效果的时间帧
    def expand(self):
        return self.age <= 1.5

    # 检查粒子是否仍在生命雕期内
    def alive(self):
        return self.age < - self.lifespan

    def ignite(cv):
        t = time()
        # 烟花列表
        explode_points = []
        wait_time = randint(10, 100)
        # 熳炸的个数
        numb_explode = randint(6, 10)
        for point in range(numb_explode):
                # 爆炸粒子列表
                objects = []
                # 爆炸x轴
                x_cordi = randint(50, 550)
                # 爆炸y轴
                y_cordi = randint(50, 150)
                speed = uniform(0.5, 1.5)
                size = uniform(0.5, 3)
                color = choice(colors)
                # 爆炸的绽放速度
                explosion_speed = uniform(0.2, 1)
                # 爆炸的粒子数半径
                total_particles = randint(10, 50)
                for i in range(1, total_particles):
                    r = fireworks(cv, idx=i, total=total_particles, explosion_speed=explosion_speed,
                                  vx=speed, vy=speed, color=color, size=size, lifespan=uniform(0.6, 1.75))
                    # 添加进粒子列表里
                    objects.append(r)
                    # 把粒子列表添加到烟花歹表
                    explode_points.append(objects)
                    total_time = 0.0
                    # 在 1.8 秒时间帧内保持更新
                    while total_time < 1.8:
                        # 让画面暂停
                        sleep(0.015)
                        # 更新总时间
                        total_time += 0.015
                    # 吊噺时间
                    tnew = time()
                    t, dt = tnew, tnew - t
                    # 遍历烟花列表
                    for point in explode_points:
                        # 遍历烟花里的粒子列表
                        for item in point:
                            # 更新时间
                            item.update(dt)
                        # 刷新页面
                        cv.update()
                        total_time += dt
                        root.after(wait_time, cv.ignite, cv)

if __name__ == "__main__":
    root = tk.Tk()
    # 绘制一个画布
    cv = tk.Canvas(root, height=400, width=600)
    # 背景图
    image = Image.open("img.png")
    photo = ImageTk.PhotoImage(image)
    # 在画板上绘制一张图片
    cv.create_image(0, 0, image=photo, anchor='nw')
    cv.pack()
    root.protocol("WM_DELETE_WINDOW", close)
    root.after(100, ignite, cv)
    # 生成窗口
    root.mainloop()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值