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烟花表白源代码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-02-24

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

做了一个Python的小项目.利用了一点python的可视化技巧,做出烟花绽放的效果,文章的灵感来自网络上一位大神. 一.编译环境 Pycharm 二.模块 1.tkinter:这个小项目的主角,是一个python图形模块.且Python3已经自带了该模块,不用另外安装.它有点像java中的swing图形模块(由众多组件集成,组件通过创建实例添加,组件通过坐标定位在窗口上). 2.PIL:Python Imaging Library,是Python平台的图像处理标准模块.在Python3也是自带

python实现浪漫的烟花秀

无意中看到一段用Tkinter库写的放烟花的程序,就跟着跑了一遍. 设计理念:通过让画面上一个粒子分裂为X数量的粒子来模拟爆炸效果.粒子会发生"膨胀",意思是它们会以恒速移动且相互之间的角度相等.这样就能让我们以一个向外膨胀的圆圈形式模拟出烟花绽放的画面.经过一定时间后,粒子会进入"自由落体"阶段,也就是由于重力因素它们开始坠落到地面,仿若绽放后熄灭的烟花. 首先我们写一个粒子类,表示烟花事件中的每个粒子,包含大小,颜色,位置,速度等属性以及粒子经历的三个阶段的函数

python实现烟花小程序

本文实例为大家分享了python实现烟花小程序的具体代码,供大家参考,具体内容如下 ''' FIREWORKS SIMULATION WITH TKINTER *self-containing code *to run: simply type python simple.py in your console *compatible with both Python 2 and Python 3 *Dependencies: tkinter, Pillow (only for backgroun

python运行其他程序的实现方法

python运行其他程序的实现方法              这里提供了两种实现方法,一.os.system()函数和 使用ShellExecute函数运行其他程序及实现代码,大家可以参考下, 一 使用os.system()函数运行其他程序 打开系统的记事本程序 >>>import os >>> os.system('notepad') 0 >>> os.system('notepad python.txt') 0 二 使用ShellExecute函数

go和python调用其它程序并得到程序输出

在c语言中可以用system函数调用系统命令并得到输出,通过输出重定向也可以将程序执行的输出保存到文件以供使用,但用起来不是很方便.我这里介绍下用python和go语言的实现方式,可以将其它程序的输出直接保存成变量供程序使用. 下面的示例用的是ls命名,需要安装MinGW,并将"C:\MinGW\msys\1.0\bin"加入环境变量. 一.用python调用其它程序,并得到输出 示例代码: 复制代码 代码如下: import osvar = os.popen('ls -l').rea

python执行等待程序直到第二天零点的方法

本文实例讲述了python执行等待程序直到第二天零点的方法.分享给大家供大家参考.具体分析如下: 如果需要通过python每天凌晨定时执行执行程序,可以使用下面的代码进行等待操作,无论什么时候执行系统都会等待到第二天凌晨才执行后面的程序. def waitToTomorrow(): """Wait to tommorow 00:00 am""" tomorrow = datetime.datetime.replace(datetime.datet

使用Python写CUDA程序的方法

使用Python写CUDA程序有两种方式: * Numba * PyCUDA numbapro现在已经不推荐使用了,功能被拆分并分别被集成到accelerate和Numba了. 例子 numba Numba通过及时编译机制(JIT)优化Python代码,Numba可以针对本机的硬件环境进行优化,同时支持CPU和GPU的优化,并且可以和Numpy集成,使Python代码可以在GPU上运行,只需在函数上方加上相关的指令标记, 如下所示: import numpy as np from timeit

python实现应用程序在右键菜单中添加打开方式功能

最近项目组开发的一个小工具想要在右键菜单中添加打开方式,以有道云笔记为例进行了需求拆解和代码编写 1.需求拆解: 如何实现手动添加右键菜单的打开方式: Step1:打开注册表编辑器,Win+R->输入 "regedit" Step2:在HKEY_CLASSES_ROOT/*/shell (或者HKEY_LOCAL_MACHINE/SOFTWARE/Classes/*/shell ,两个目录是一样的) 添加一个key:YNote,然后在该项中新建项command,然后再编辑字符串,

Python实战小程序利用matplotlib模块画图代码分享

Python中的数据可视化 matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地进行制图.而且也可以方便地将它作为绘图控件. 实战小程序:画出y=x^3的散点图 样例代码如下: #coding=utf-8 import pylab as y #引入pylab模块 x = y.np.linspace(-10, 10, 100) #设置x横坐标范围和点数 y.plot(x, x*x*x,'or') #生成图像 ax = y.gca() a

简单的python协同过滤程序实例代码

本文研究的主要是python协同过滤程序的相关内容,具体介绍如下. 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看最近有什么好的电影推荐.在问的时候,都习惯于问跟自己口味差不多的朋友,这就是协同过滤的核心思想. 这个程序完全是为了应付大数据分析与计算的课程作业所写的一个小程序,先上程序,一共55行.不在意细节的话,55行的程序已经表现出了协同过滤的特性了.就是对每一个用户找4个最接近的用户,然后进行推荐,在选择

Python聊天室程序(基础版)

本文实例为大家分享了Python聊天室程序的具体代码,供大家参考,具体内容如下 客户端代码: # Filename: socketClient.py import socket import sys import threading # Client GUI from tkinter import * import Pmw # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Con

python操作小程序云数据库实现简单的增删改查功能

不止python,你可以利用任何语言那实现通过http请求来操作你自己的小程序云数据库了 背景 也是在最近吧,小程序更新了云开发 HTTP API 文档,提供了小程序外访问云开发资源的能力,使用 HTTP API 开发者可在已有服务器上访问云资源,实现与云开发的互通. 原本云数据库还是相对封闭的,只能通过自己的小程序或者云函数来进行访问,而现在,你只要调用官方提供的接口就能实现对云函数的增删改查了. 这里通过 python 作为演示来进行简单的测试,当然你也可以使用 java , php 等任何