天天敲代码的朋友,有没有想过代码也可以变得很酷炫又浪漫?今天就教大家用Python模拟出绽放的烟花,工作之余也可以随时让程序为自己放一场烟花秀。

python炫酷烟花表白源代码

这个有趣的小项目并不复杂,只需一点可视化技巧,100余行Python代码和程序库Tkinter,最后我们就能达到下面这个效果:

学完本教程后,你也能做出这样的烟花秀。

整体概念梳理

我们的整个理念比较简单。

如上图示,我们这里通过让画面上一个粒子分裂为X数量的粒子来模拟爆炸效果。粒子会发生“膨胀”,意思是它们会以恒速移动且相互之间的角度相等。这样就能让我们以一个向外膨胀的圆圈形式模拟出烟花绽放的画面。经过一定时间后,粒子会进入“自由落体”阶段,也就是由于重力因素它们开始坠落到地面,仿若绽放后熄灭的烟花。

(推荐学习:编程学习课程)

基本知识:用Python和Tkinter设计烟花

这里不再一股脑把数学知识全丢出来,我们边写代码边说理论。首先,确保你安装和导入了Tkinter,它是Python的标准 GUI 库,广泛应用于各种各样的项目和程序开发,在Python中使用 Tkinter 可以快速的创建 GUI 应用程序。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

除了Tkinter之外,为了能让界面有漂亮的背景,我们也导入PIL用于图像处理,以及导入其它一些包,比如time,random和math。它们能让我们更容易的控制烟花粒子的运动轨迹。

Tkinter应用的基本设置如下:root = tk.Tk()

为了能初始化Tkinter,我们必须创建一个Tk()根部件(root widget),它是一个窗口,带有标题栏和由窗口管理器提供的其它装饰物。该根部件必须在我们创建其它小部件之前就创建完毕,而且只能有一个根部件。w = tk.Label(root, text="Hello Tkinter!")

这一行代码包含了Label部件。该Label调用中的第一个参数就是父窗口的名字,即我们这里用的“根”。关键字参数“text”指明显示的文字内容。你也可以调用其它小部件:Button,Canvas等等。w.pack()

root.mainloop()

接下来的这两行代码很重要。这里的打包方法是告诉Tkinter调整窗口大小以适应所用的小部件。窗口直到我们进入Tkinter事件循环,被root.mainloop()调用时才会出现。在我们关闭窗口前,脚本会一直在停留在事件循环。

将烟花绽放转译成代码

现在我们设计一个对象,表示烟花事件中的每个粒子。每个粒子都会有一些重要的属性,支配了它的外观和移动状况:大小,颜色,位置,速度等等。'''

particles 类

粒子在空中随机生成随机,变成一个圈、下坠、消失

属性:

- id: 粒子的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

self.y = y

self.initial_speed = explosion_speed

self.vx = vx

self.vy = vy

self.total = total

self.age = 0self.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

如果我们回过头想想最开始的想法,就会意识到必须确保每个烟花绽放的所有粒子必须经过3个不同的阶段,即“膨胀”“坠落”和“消失”。 所以我们向粒子类中再添加一些运动函数,如下所示:def update(self, 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.vx = move_x/(float(dt)*1000)

self.vy = move_y/(float(dt)*1000)

self.cv.move(self.cid, move_x, move_y)

# 以自由落体坠落

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

使用Tkinter模拟

现在我们将粒子的移动概念化,不过很明显,一个烟花不能只有一个粒子,一场烟花秀也不能只有一个烟花。我们下一步就是让Python和Tkinter以我们可控的方式向天上连续“发射”粒子。

到了这里,我们需要从操作一个粒子升级为在屏幕上展现多个烟花及每个烟花中的多个粒子。

我们的解决思路如下:创建一列列表,每个子列表是一个烟花,其包含一列粒子。每个列表中的例子有相同的x,y坐标、大小、颜色、初始速度。numb_explode = randint(6,10)

# 为所有模拟烟花绽放的全部粒子创建一列列表

for point in range(numb_explode):

objects = []

x_cordi = randint(50,550)

y_cordi = randint(50, 150)

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 = part(cv, idx = i, total = total_particles, explosion_speed = explosion_speed, x = x_cordi, y = y_cordi,

color=color, size = size, lifespan = uniform(0.6,1.75))

objects.append(r)

explode_points.append(objects)

我们下一步就是确保定期更新粒子的属性。这里我们设置让粒子每0.01秒更新它们的状态,在1.8秒之后停止更新(这意味着每个粒子的存在时间为1.6秒,其中1.2秒为“绽放”状态,0.4秒为“坠落”状态,0.2秒处于Tkinter将其完全移除前的边缘状态)。total_time = .0

# 在1.8秒时间帧内保持更新

while total_time < 1.8:

sleep(0.01)

tnew = time()

t, dt = tnew, tnew - t

for point in explode_points:

for part in point:

part.update(dt)

cv.update()

total_time += dt

现在,我们只需将最后两个gist合并为一个能被Tkinter调用的函数,就叫它simulate()吧。该函数会展示所有的数据项,并根据我们设置的时间更新每个数据项的属性。在我们的主代码中,我们会用一个alarm处理模块after()调用此函数,after()会等待一定的时间,然后再调用函数。

我们这里设置让Tkinter等待100个单位(1秒钟)再调取simulate。if __name__ == '__main__':

root = tk.Tk()

cv = tk.Canvas(root, height=600, width=600)

# 绘制一个黑色背景

cv.create_rectangle(0, 0, 600, 600, fill="black")

cv.pack()

root.protocol("WM_DELETE_WINDOW", close)

# 在1秒后才开始调用stimulate()

root.after(100, simulate, cv)

root.mainloop()

好了,这样我们就用Python代码放了一场烟花秀:

本文只一个简单版本,等进一步熟悉Tkinter后,还可以添加更多颜色更漂亮的背景照片,让代码为你绽放更美的烟花!

以下是全部代码: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 = 0self.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=400, width=600)

# 选一个好看的背景会让效果更惊艳!

image = Image.open("./image.jpg")

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()

众多python培训视频,尽在python学习网,欢迎在线学习!

python炫酷烟花表白程序_python炫酷烟花表白源代码相关推荐

  1. python监控linux运行程序_python linux监控程序

    Pyinotify – Linux中实时监控文件系统更改 Pyinotify 是一个简单而实用的 Python 模块,它用于通过 inotify 实时监控Linux文件系统的更改.用于在Linux中实 ...

  2. python定义类的程序_python扫码签到程序python中如何定义类

    什么是类? 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 什么是方法? 类中的函数即为方法 如何定义一个类? 定义类,语法格式如下: < ...

  3. python中用函数编写程序_python编写程序,在程序中定义一个函数,计算1+1/2+1/3+1/4+……+1/n...

    python语言编写的程序需要运行库.Python(英语发音:/?pa?θ?n/),是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum于1989年发明,第一个公开发行版发行于 ...

  4. python 开发窗体应用程序_Python如何编写窗体程序

    Python如何编写窗体程序 python和很多软件的用法其实差不多,只是代码更为简洁,代码量没这么多. 窗体的写法也和java类似,现在举个例子:编写一个点名器,有一个按钮当被点击时,会随机产生一个 ...

  5. python动态心形代码_Python实现酷炫的动态交互式数据可视化,附代码!

    (关注公众号AI新视野,发送'资料'二字,免费获取50G人工智能视频教程!) 本文介绍如何创建交互式图表和小组件,使用python做数据可视化.涉及的python库有:Plotly, Bokeh, n ...

  6. python条件语句代码例子_Python 炫技操作:条件语句的七种写法

    原标题:Python 炫技操作:条件语句的七种写法 作者 | 写代码的明哥 责编 | 郭芮 有的人说 Python 入门容易,但是精通难的语言,这点我非常赞同. Python 语言里有许多(而且是越来 ...

  7. python里的英文歌_python下载酷狗音乐上的歌曲

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:TM0831 准备工作:Python3.5 Pycharm 使用到的 ...

  8. python海象运算符怎么用_Python 炫技操作:海象运算符的三种用法

    Python 版本发展非常快,如今最新的版本已经是 Pyhton 3.9,即便如此,有很多人甚至还停留在 3.6 或者 3.7,连 3.8 还没用上. 很多 Python 3.8 的特性还没来得及了解 ...

  9. python自动下载酷狗音乐_Python下载酷狗音乐

    #encoding=utf-8 import re import json import time import requests import os def search(song_name): & ...

最新文章

  1. CodeGen准备存储库
  2. 同步服务老是报错_悬而未决:MYSQL配置好主从同步后没有报错,但数据一直没有同步过来是什么原因? | 学步园...
  3. LintCode 16. 带重复元素的排列
  4. 老旗舰华为能用上鸿蒙吗,华为完全开放鸿蒙,未来所有手机都能用鸿蒙系统?...
  5. python征程1.4(初识python)
  6. Ghost网络克隆详细步骤教程
  7. 博弈论分析题_最新博弈论复习题及答案分析
  8. Epub电子书实战解析
  9. mybatis报错:Error evaluating expression
  10. php redis序列化,php session之存储在redis的方法
  11. 利用windows事件管理器定位程序闪退错误
  12. mysql insert 阻塞_insert遭遇阻塞
  13. C++ 调用 Python 代码 - Clion QT混合编程 ,各取长处。
  14. JavaScript 编程精解 中文第三版 二十、Node.js
  15. [附源码]计算机毕业设计JAVA宠物狗领养网站
  16. CCPC2018 桂林 D Bits Reverse
  17. 马上消费首份报告曝光,聚焦6大方向践行社会责任
  18. AVR USART接收中断程序
  19. OAuth 2.0安全案例回顾
  20. 接口测试面试题<一>

热门文章

  1. zookeeper本地下载与安装
  2. leetcode_1465
  3. 教你一招轻松批量处理图片,无需ps新手也能轻松完成
  4. UI设计专业术语大汇总啦!
  5. 教你这样找到Mac“其他”文件并删除它
  6. 角蜂鸟AI视觉套件1:开箱和开发环境搭建
  7. 听歌乐一乐。一首未卜之路送给苦逼的程序员
  8. 【软考系统架构设计师】2014年下系统架构师论文写作历年真题
  9. 使用USBWriter做U盘启动盘后容量变小的解决办法
  10. Unity3d解决Fbx动画不可用:The AnimationClip ‘xxx‘ used by the Animation component ‘xxx‘ must be marked...