直接上程式碼!
# -*- coding: utf-8 -*-
import math, random,time
import threading
import tkinter as tk
import re
#import uuid
Fireworks=[]
maxFireworks=8
height,width=600,600
class firework(object):
def __init__(self,color,speed,width,height):
#uid=uuid。uuid1()
self。radius=random。randint(2,4) #
粒子半徑
為2~4畫素
self。color=color #粒子顏色
self。speed=speed #speed是1。5-3。5秒
self。status=0 #在煙花未爆炸的情況下,status=0;爆炸後,status>=1;當status>100時,煙花的生命期終止
self。nParticle=random。randint(20,30) #粒子數量
self。center=[random。randint(0,width-1),random。randint(0,height-1)] #煙花隨機中心座標
self。oneParticle=[] #
原始粒子
座標(100%狀態時)
self。rotTheta=random。uniform(0,2*math。pi) #橢圓平面旋轉角
#橢圓引數方程:x=a*cos(theta),y=b*sin(theta)
#ellipsePara=[a,b]
self。ellipsePara=[
random。randint
(30,40),random。randint(20,30)]
theta=2*math。pi/self。nParticle
for i in range(self。nParticle):
t=random。uniform(-1。0/16,1。0/16) #產生一個 [-1/16,1/16) 的
隨機數
x,y=self。ellipsePara[0]*math。cos(theta*i+t), self。ellipsePara[1]*math。sin(theta*i+t) #
橢圓引數方程
xx,yy=x*math。cos(self。rotTheta)-y*math。sin(self。rotTheta), y*math。cos(self。rotTheta)+x*math。sin(self。rotTheta) #
平面旋轉方程
self。oneParticle。append([xx,yy])
self。curParticle=self。oneParticle[0:] #當前粒子座標
self。thread=threading。Thread(target=self。extend) #建立執行緒物件
def extend(self): #粒子群狀態變化函式執行緒
for i in range(100):
self。status+=1 #更新狀態標識
self。curParticle=[[one[0]*self。status/100, one[1]*self。status/100] for one in self。oneParticle] #更新粒子群座標
time。sleep(self。speed/50)
def explode(self):
self。thread。setDaemon(True) #把現程設為
守護執行緒
self。thread。start() #
啟動執行緒
def __repr__(self):
return (‘color:{color}\n’
‘speed:{speed}\n’
‘number of particle: {np}\n’
‘center:[{cx} , {cy}]\n’
‘ellipse:a={ea} , b={eb}\n’
‘particle:\n{p}\n’
)。format(color=self。color,speed=self。speed,np=self。nParticle,cx=self。center[0],cy=self。center[1],p=str(self。oneParticle),ea=self。ellipsePara[0],eb=self。ellipsePara[1])
def colorChange(fire):
rgb=re。findall(r‘(。{2})’,fire。color[1:])
cs=fire。status
f=lambda x,c: hex(int(int(x,16)*(100-c)/30))[2:] #當粒子壽命到70%時,顏色開始線性衰減
if cs>70:
ccr,ccg,ccb=f(rgb[0],cs),f(rgb[1],cs),f(rgb[2],cs)
else:
ccr,ccg,ccb=rgb[0],rgb[1],rgb[2]
return ‘#{0:0>2}{1:0>2}{2:0>2}’。format(ccr,ccg,ccb)
def appendFirework(n=1): #遞迴生成煙花物件
if n>maxFireworks or len(Fireworks)>maxFireworks:
pass
elif n==1:
cl=‘#{0:0>6}’。format(hex(int(random。randint(0,16777215)))[2:]) # 產生一個0~16777215(0xFFFFFF)的隨機數,作為隨機顏色
a=firework(cl,random。uniform(1。5,3。5),width,height)
Fireworks。append( {‘particle’:a,‘points’:[]} ) #建立粒子顯示列表,‘particle’為一個煙花物件,‘points’為每一個粒子顯示時的物件變數集
a。explode()
else:
appendFirework()
appendFirework(n-1)
def show(c):
for p in Fireworks: #每次重新整理顯示,先把已有的所以粒子全部刪除
for pp in p[‘points’]:
c。delete(pp)
for p in Fireworks: #根據每個煙花物件,計算其中每個粒子的顯示物件
oneP=p[‘particle’]
if oneP。status==100: #狀態標識為100,說明煙花壽命結束
Fireworks。remove(p) #移出當前煙花
appendFirework() #新增一個煙花
continue
else:
li=[[int(cp[0]*2)+oneP。center[0],int(cp[1]*2)+oneP。center[1]] for cp in oneP。curParticle] #把中心為原點的橢圓平移到隨機圓心
座標
上
color=colorChange(oneP) #根據煙花當前狀態計算當前顏色
for pp in li:
p[‘points’]。append(c。create_oval(pp[0]-oneP。radius, pp[1]-oneP。radius, pp[0]+oneP。radius, pp[1]+oneP。radius, fill=color)) #繪製煙花每個粒子
root。after(50, show,c) #回撥,每50ms重新整理一次
if __name__==‘__main__’:
appendFirework(maxFireworks)
root = tk。Tk()
cv = tk。Canvas(root, height=height, width=width)
cv。create_rectangle(0, 0, width, height, fill=“black”)
cv。pack()
root。after(50, show,cv)
root。mainloop()
2:效果圖
點選連結加入群聊【Python學習交流群】: