新年快乐! python实现绚烂的烟花绽放效果


Posted in Python onJanuary 30, 2019

做了一个Python的小项目。利用了一点python的可视化技巧,做出烟花绽放的效果,文章的灵感来自网络上一位大神。

一.编译环境

Pycharm

二.模块

1.tkinter:这个小项目的主角,是一个python图形模块。且Python3已经自带了该模块,不用另外安装。它有点像java中的swing图形模块(由众多组件集成,组件通过创建实例添加,组件通过坐标定位在窗口上)。

2.PIL:Python Imaging Library,是Python平台的图像处理标准模块。在Python3也是自带的,在这个项目中用于背景图片的导入。

3.time:相信这个模块大家都不会陌生,导入它用来控制烟花的绽放,坠落及消失时间。

4.random:随机数模块,用于生成烟花随机坐标点,随机绽放速度,随机消失时间。

5.math:这个模块大家应该也很熟悉了,导入它的目的是使烟花绽放的粒子以一定角度散开。

三.效果

新年快乐! python实现绚烂的烟花绽放效果

项目最终实现的效果就跟上面一样了。

四.代码

以下是我学习(copy)了那位大神的代码,再添加了一些浅显的注解。

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.5
#listof colors,can choose randomly or use as queue(FIFO
colors=['red','blue','yellow','white','green','orange','purple','seagreen','indigo','cornflowerblue']
'''
create a class for particles粒子
particles are emitted almost randomly on the sky,
forming around(组成一个圈) of circle(a star)before falling and getting removed from canvas

Attributes(属性):
id:每个特定烟花的标识符
x,y:烟花的绽放坐标
vx,vy:烟花的绽放速度
total:一颗烟花里的星星总数
age:一颗星星会在画布上停留多久
color:自我移植
cv:画布
lifespan:星星在画布上停留的最后时间
'''
class part:#为每一个烟花绽放出来的粒子单独构建一个类的对象
 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#烟花的绽放x轴
  self.y=y#烟花的绽放x轴
  self.initial_speed=explosion_speed#初速度
  self.vx=vx#外放x轴速度
  self.vy=vy#外放y轴速度
  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)#create_oval()创建一个椭圆,参数为左上x,左上y,右下x,右下y,填满的颜色,该函数返回一个id
  self.lifespan=lifespan#应该停留时间
 def update(self,dt):#更新数据,已停留时间增加
  self.age+=dt
  #粒子膨胀
  if self.alive() and self.expand():#如果停留时间(2s)足够&&膨胀时间(1.2s)足够
   move_x=cos(radians(self.id*360/self.total))*self.initial_speed#粒子的x轴继续膨胀
   move_y=sin(radians(self.id*360/self.total))*self.initial_speed#粒子的y轴继续膨胀
   self.cv.move(self.cid, move_x, move_y)#根据id把画布上的粒子移动x和y个距离
   self.vx=move_x/(float(dt)*1000)
  #以自由落体坠落
  elif self.alive():#如果只是停留时间足够,说明膨胀到最大了,应该准备下坠
   move_x=cos(radians(self.id*360/self.total))#x轴继续膨胀
   self.cv.move(self.cid,self.vx+move_x,self.vy+GRAVITY*dt)#而y轴按照重力因素做落体运动,但实际上这个重力是v而不是a
   self.vy+=GRAVITY*dt#更新一下y轴

  elif self.cid is not None:#如果粒子的生命周期已过,就将其移除
   cv.delete(self.cid)#删除该粒子对象
   self.cid=None
 #定义膨胀效果的时间帧
 def expand(self):
  return self.age<=1.2#膨胀时间小于1.2s
 #检查粒子是否仍在生命周期内
 def alive(self):#已停留时间是不是比应该停留时间短
  return self.age<=self.lifespan
'''
烟花模拟回路:
递归调用来在画布上重复发出新的烟火
通过每个“部件”对象内部的更新协议,每次调用时都要在画布上创建并绘制列表(星列表,每个星列表成员都是粒子列表)来重复地在画布上发出新的焰火
'''
#生成新的一轮爆炸
def simulate(cv):
 t=time()#time()函数返回自1970年后经过的浮点秒数,精确到小数点后6位
 explode_points=[]#爆炸点列表--烟花列表
 wait_time=randint(10,100)#随机生成一个int n,10<=n<=100
 numb_explode=randint(6,10)#爆炸的个数是6~10
 #为所有模拟烟花绽放的全部例子创建一列列表
 for point in range(numb_explode):#遍历爆炸的个数
  objects=[]#这是每个点的爆炸粒子列表
  x_cordi=randint(50,550)#每个点的爆炸x轴
  y_cordi=randint(50,150)#爆炸y轴
  speed=uniform(0.5,1.5)#随机生成一个float speed,0.5<=speed<1.5
  size=uniform(0.5,3)#随机生成一个float size,0.5<=size<3
  color=choice(colors)#choice()是python内置函数,随机返回元组,列表,或字符串的一个成员
  explosion_speed=uniform(0.2,1)#爆炸的绽放速度也要随机出来
  total_particles=randint(10,50)#爆炸出来的粒子数半径也随机
  for i in range(1,total_particles):#同一个烟花爆炸出来的粒子的大小,速度,坐标都是相同的
   r = part(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#先把时间置0
 #在1.8秒时间帧内保持更新
 while total_time<1.8:
  sleep(0.01)#让画面暂停0.01s
  tnew=time()#刷新时间
  t,dt=tnew,tnew-t#时间等于新时间,与上次时间间隔为tnew-t
  for point in explode_points:#遍历烟花列表
   for item in point:#遍历烟花里的粒子列表
    item.update(dt)#更新时间
  cv.update()#刷新页面
  total_time+=dt#为上面的while循环增加时间
 root.after(wait_time,simulate,cv)#将组件置于其他组件之后,就是放在最顶层,覆盖下面的,这里递归第哦啊用了自己,形成新的一轮爆炸
def close(*ignore):
 #打开模拟循环并关闭窗口
 global root
 root.quit()

if __name__=="__main__":
 root=tk.Tk()
 cv=tk.Canvas(root,height=600,width=700)#绘制一个画布
 #绘制一个黑色背景
 #cv.create_rectangle(0,0,600,600,fill="black")
 #use a nice background image
 image=Image.open("L:\PyCharm Community Edition 2018.2.2\Python_program\image.jpg")
 photo=ImageTk.PhotoImage(image)
 cv.create_image(0,0,image=photo,anchor='nw')#在画板上绘制一张图片
 cv.pack()#把cv添加进去
 root.protocol("WM_DELETE_WINDOW",close)
 #在0.1s后才开始调用stimulate()
 root.after(100,simulate,cv)#调用stimulate生成一轮烟花绽放效果
 root.mainloop()#执行root,生成窗口
#让我更加明白了python的一切皆对象

五.结尾

这篇博客暂时就这样,如果有机会会重新做一遍,不过最大的可能就是遥遥无期了。先打算对项目做如下修改:

1.增加鼠标交互功能,用户鼠标点击位置额外生成烟花绽放;

2.增加文字绘制功能,在背景图中隐藏有字样,烟花绽放后落于字样中的粒子不消失,而是定格在窗口中。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 操作MySQL详解及实例
Apr 30 Python
Python导入模块时遇到的错误分析
Aug 30 Python
python获取指定字符串中重复模式最高的字符串方法
Jun 29 Python
解决python selenium3启动不了firefox的问题
Oct 13 Python
Python使用while循环花式打印乘法表
Jan 28 Python
浅析Python 实现一个自动化翻译和替换的工具
Apr 14 Python
Python八皇后问题解答过程详解
Jul 29 Python
Python实现对adb命令封装
Mar 06 Python
python图片剪裁代码(图片按四个点坐标剪裁)
Mar 10 Python
Python进程间通信multiprocess代码实例
Mar 18 Python
Python 的 sum() Pythonic 的求和方法详细
Oct 16 Python
python实现层次聚类的方法
Nov 01 Python
python+selenium 定位到元素,无法点击的解决方法
Jan 30 #Python
解决Python selenium get页面很慢时的问题
Jan 30 #Python
对python实现模板生成脚本的方法详解
Jan 30 #Python
ActiveMQ:使用Python访问ActiveMQ的方法
Jan 30 #Python
python 发送和接收ActiveMQ消息的实例
Jan 30 #Python
Python批量生成特定尺寸图片及图画任意文字的实例
Jan 30 #Python
理想高通滤波实现Python opencv示例
Jan 30 #Python
You might like
如何将数据从文本导入到mysql
2006/10/09 PHP
php 无限级数据JSON格式及JS解析
2010/07/17 PHP
批量去除PHP文件中bom的PHP代码
2012/03/13 PHP
PHP输出日历表代码实例
2015/03/27 PHP
php文件包含目录配置open_basedir的使用与性能详解
2017/04/03 PHP
Laravel Eloquent ORM 多条件查询的例子
2019/10/10 PHP
网页的标准,IMG不支持onload标签怎么办
2006/06/29 Javascript
在线编辑器的实现原理(兼容IE和FireFox)
2007/03/09 Javascript
JavaScript中的私有/静态属性介绍
2012/07/26 Javascript
javascript实现随机显示星星特效
2016/01/28 Javascript
JavaScript File API实现文件上传预览
2016/02/02 Javascript
Vue.js路由vue-router使用方法详解
2017/03/20 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
小程序页面动态配置实现方法
2019/02/05 Javascript
react中hook介绍以及使用教程
2020/12/11 Javascript
Python读写Excel文件的实例
2013/11/01 Python
Python利用正则表达式匹配并截取指定子串及去重的方法
2015/07/30 Python
TensorFlow入门使用 tf.train.Saver()保存模型
2018/04/24 Python
python得到windows自启动列表的方法
2018/10/14 Python
Python3 执行系统命令并获取实时回显功能
2019/07/09 Python
Python 一键获取百度网盘提取码的方法
2019/08/01 Python
Pytorch Tensor基本数学运算详解
2019/12/30 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
Python WebSocket长连接心跳与短连接的示例
2020/11/24 Python
美国领先的医疗警报服务:Philips Lifeline
2018/03/12 全球购物
世界上最大的高分辨率在线图片库:Alamy
2018/07/07 全球购物
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
丝芙兰意大利官方网站:Sephora.it
2019/12/13 全球购物
介绍一下HDLC(High-Level Data Link Control)高层数据链路协议
2012/01/21 面试题
常用UNIX 命令(Linux的常用命令)
2015/12/26 面试题
医科大学毕业生自荐信
2014/02/03 职场文书
党章培训心得体会
2014/09/04 职场文书
领导班子在批评与自我批评座谈会上的发言
2014/09/28 职场文书
2014年设计师工作总结
2014/11/25 职场文书
springboot读取nacos配置文件
2022/05/20 Java/Android
win10蓝屏0xc0000001安全模式进不了怎么办?win10出现0xc0000001的解决方法
2022/08/05 数码科技