python炫酷烟花源代码
python实现浪漫的烟花秀无意中看到一段用tkinter库写的放烟花的程序,就跟着跑了一遍。
设计理念:通过让画面上一个粒子分裂为x数量的粒子来模拟爆炸效果。粒子会发生“膨胀”,意思是它们会以恒速移动且相互之间的角度相等。这样就能让我们以一个向外膨胀的圆圈形式模拟出烟花绽放的画面。经过一定时间后,粒子会进入“自由落体”阶段,也就是由于重力因素它们开始坠落到地面,仿若绽放后熄灭的烟花。
首先我们写一个粒子类,表示烟花事件中的每个粒子,包含大小,颜色,位置,速度等属性以及粒子经历的三个阶段的函数,即:膨胀、坠落、消失。
|
''' particles 类 粒子在空中随机生成随机,变成一个圈、下坠、消失 属性: - id: 粒子的id - x, y: 粒子的坐标 - vx, vy: 在坐标的变化速度 - total: 总数 - age: 粒子存在的时长 - color: 颜色 - cv: 画布 - lifespan: 最高存在时长 ''' class particle: 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 self .x = x self .y = y self .initial_speed = explosion_speed self .vx = vx 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(): 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)) # we technically don't need to update x, y because move will do the job self .cv.move( self .cid, self .vx + move_x, self .vy + gravity * dt) self .vy + = gravity * dt # 移除超过最高时长的粒子 elif self .cid is not none: cv.delete( self .cid) self .cid = none # 扩大的时间 def expand ( self ): return self .age < = 1.2 # 粒子是否在最高存在时长内 def alive( self ): return self .age < = self .lifespan |
接下来我们需要创建一列列表,每个子列表是一个烟花,其包含一列粒子,每个列表中的粒子有相同的x,y坐标、大小、颜色、初始速度。
源码如下:
|
import tkinter as tk from pil import image, imagetk from time import time, sleep from random import choice, uniform, randint from math import sin, cos, radians # 模拟重力 gravity = 0.05 # 颜色选项(随机或者按顺序) colors = [ 'red' , 'blue' , 'yellow' , 'white' , 'green' , 'orange' , 'purple' , 'seagreen' , 'indigo' , 'cornflowerblue' ] ''' particles 类 粒子在空中随机生成随机,变成一个圈、下坠、消失 属性: - id: 粒子的id - x, y: 粒子的坐标 - vx, vy: 在坐标的变化速度 - total: 总数 - age: 粒子存在的时长 - color: 颜色 - cv: 画布 - lifespan: 最高存在时长 ''' class particle: 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 self .x = x self .y = y self .initial_speed = explosion_speed self .vx = vx 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(): 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)) # we technically don't need to update x, y because move will do the job self .cv.move( self .cid, self .vx + move_x, self .vy + gravity * dt) self .vy + = gravity * dt # 移除超过最高时长的粒子 elif self .cid is not none: cv.delete( self .cid) self .cid = none # 扩大的时间 def expand ( self ): return self .age < = 1.2 # 粒子是否在最高存在时长内 def alive( self ): return self .age < = self .lifespan ''' 循环调用保持不停 ''' def simulate(cv): t = time() explode_points = [] wait_time = randint( 10 , 100 ) numb_explode = randint( 6 , 10 ) # 创建一个所有粒子同时扩大的二维列表 for point in range (numb_explode): objects = [] x_cordi = randint( 50 , 550 ) 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 = particle(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 )) objects.append(r) explode_points.append(objects) total_time = . 0 # 1.8s内一直扩大 while total_time < 1.8 : sleep( 0.01 ) 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, simulate, cv) def close( * ignore): """退出程序、关闭窗口""" global root root.quit() if __name__ = = '__main__' : root = tk.tk() cv = tk.canvas(root, height = 360 , width = 480 ) # 选一个好看的背景会让效果更惊艳! image = image. open ( "./image.jpg" alt="python炫酷烟花源代码(python实现浪漫的烟花秀)" border="0" /> photo = imagetk.photoimage(image) cv.create_image( 0 , 0 , image = photo, anchor = 'nw' ) cv.pack() root.protocol( "wm_delete_window" , close) root.after( 100 , simulate, cv) root.mainloop() |
效果图(背景请忽略哈哈):
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。
原文链接:https://blog.csdn.net/neil3611244/article/details/84836520