服务器之家

服务器之家 > 正文

python实现浪漫的烟花秀

时间:2021-05-24 00:44     来源/作者:凋谢的浮华

无意中看到一段用tkinter库写的放烟花的程序,就跟着跑了一遍。

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

python实现浪漫的烟花秀

首先我们写一个粒子类,表示烟花事件中的每个粒子,包含大小,颜色,位置,速度等属性以及粒子经历的三个阶段的函数,即:膨胀、坠落、消失。

python" id="highlighter_492956">
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
'''
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坐标、大小、颜色、初始速度。

源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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")
  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实现浪漫的烟花秀

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/neil3611244/article/details/84836520

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
2021德云社封箱演出完整版 2021年德云社封箱演出在线看
2021德云社封箱演出完整版 2021年德云社封箱演出在线看 2021-03-15
返回顶部