??快到春節(jié)了,用 Python 實(shí)現(xiàn)一場(chǎng)煙花秀,增添節(jié)日的氣氛!
來(lái)源 | Python 技術(shù)
春節(jié)的腳步越來(lái)越近了,每逢春節(jié)很多地方都會(huì)燃放煙花來(lái)增添節(jié)日的氣氛,然而因環(huán)境污染的加劇,近年來(lái)不少地方已經(jīng)禁止燃放煙花了,為了彌補(bǔ)這個(gè)遺憾,本文我們來(lái)看一下如何使用 Python 來(lái)實(shí)現(xiàn)一場(chǎng)煙花秀。
實(shí)現(xiàn)
功能實(shí)現(xiàn)用到的 Python 庫(kù)包括:tkinter、PIL、time、random、math,如果之前沒(méi)有裝過(guò)第三庫(kù)的話,使用 pip install pillow 裝一下即可。
首先,我們使用 tkinter 來(lái)創(chuàng)建一個(gè)畫布,可以根據(jù)自己的喜好選一張應(yīng)景的圖片作為背景,代碼實(shí)現(xiàn)如下:
root?=?tk.Tk()
#?繪制一個(gè)畫布
cv?=?tk.Canvas(root,?height=457,?width=690)
#?背景圖
image?=?Image.open("bg.jpeg")
photo?=?ImageTk.PhotoImage(image)
#?在畫板上繪制一張圖片
cv.create_image(0,?0,?image=photo,?anchor='nw')
cv.pack()
看一下效果:

接著我們來(lái)實(shí)現(xiàn)煙花燃放的效果并在畫布上顯示。先來(lái)定義一個(gè)煙花類 fireworks,類中主要包括:初始化方法和更新數(shù)據(jù)方法。
初始化方法主要參數(shù)包括:煙花綻放坐標(biāo)軸、速度、顏色、粒子數(shù)和時(shí)間等,代碼實(shí)現(xiàn)如下:
def?__init__(self,?cv,?idx,?total,?explosion_speed,?x=0.,?y=0.,
????vx=0.,?vy=0.,?size=2.,?color='red',?lifespan=2,?**kwargs):
?self.id?=?idx
?#?煙花綻放?x?軸
?self.x?=?x
?#?煙花綻放?x?軸
?self.y?=?y
?self.initial_speed?=?explosion_speed
?#?外放?x?軸速度
?self.vx?=?vx
?#?外放?y?軸速度
?self.vy?=?vy
?#?綻放的粒子數(shù)
?self.total?=?total
?#?已停留時(shí)間
?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
當(dāng)煙花燃放過(guò)后需要進(jìn)行刷新,看一下更新方法,代碼實(shí)現(xiàn)如下:
def?update(self,?dt):
?self.age?+=?dt
?#?粒子膨脹
?if?self.alive()?and?self.expand():
??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():
??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
?#?過(guò)期移除
?elif?self.cid?is?not?None:
??cv.delete(self.cid)
??self.cid?=?None
再接著來(lái)看煙花燃放的實(shí)現(xiàn),主要元素包括:煙花的個(gè)數(shù)、爆炸的范圍和速度、停留時(shí)間和刷新時(shí)間等,代碼實(shí)現(xiàn)如下:
def?ignite(cv):
????t?=?time()
????#?煙花列表
????explode_points?=?[]
????wait_time?=?randint(10,?100)
????#?爆炸的個(gè)數(shù)
????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)
????????#?爆炸的粒子數(shù)半徑
????????total_particles?=?randint(10,?50)
????????for?i?in?range(1,?total_particles):
????????????r?=?fireworks(cv,?idx=i,?total=total_particles,
??????????????????????????explosion_speed=explosion_speed,?x=x_cordi,?y=y_cordi,
?????????????????????vx=speed,?vy=speed,?color=color,?size=size,
?????????????????????lifespan=uniform(0.6,?1.75))
????????????#?添加進(jìn)粒子列表里
????????????objects.append(r)
????????#?把粒子列表添加到煙花列表
????????explode_points.append(objects)
????total_time?=?.0
????#?在?1.8?秒時(shí)間幀內(nèi)保持更新
????while?total_time?1.8:
????????#?讓畫面暫停?0.01s
????????sleep(0.01)
????????#?刷新時(shí)間
????????tnew?=?time()
????????t,?dt?=?tnew,?tnew?-?t
????????#?遍歷煙花列表
????????for?point?in?explode_points:
????????????#?遍歷煙花里的粒子列表
????????????for?item?in?point:
????????????????#?更新時(shí)間
????????????????item.update(dt)
????????#?刷新頁(yè)面
????????cv.update()
????????total_time?+=?dt
????root.after(wait_time,?ignite,?cv)
最后,我們來(lái)看一下效果:

總結(jié)
本文我們使用 Python 實(shí)現(xiàn)了煙花燃放的特效,如果感興趣的話,可以自動(dòng)動(dòng)手試試。
-END- 往期精彩推薦 --?? -- 1、令人心動(dòng)的offer... -- 2、NBA球星數(shù)據(jù)查詢(GUI界面) -- 3、批量下載bilibili視頻 --? 留下你的“在看”唄!

