Code example of python fireworks effect | CSDN creation punch in

Posted by ksandom on Tue, 25 Jan 2022 15:16:23 +0100

1, Overall concept combing

In this article, the code example of python fireworks effect is compiled for you. Friends who are interested in this can learn and refer to it.

Friends who knock code every day, have you ever thought that code can also become very cool and romantic? Today, I'll teach you to simulate the blooming fireworks with Python. After work, you can also let the program set off a fireworks show for yourself at any time.
This interesting small project is not complicated. It only needs a little visualization skills, more than 100 lines of Python code and Tkinter library. Finally, we can achieve the following results:

After learning this tutorial, you can also make such a fireworks show.

2, Basics: designing fireworks with Python and Tkinter

Our whole idea is relatively simple.

As shown in the figure above, we simulate the explosion effect by splitting a particle on the picture into X particles. Particles "expand", meaning they move at a constant speed and at equal angles to each other. In this way, we can simulate the picture of fireworks blooming in the form of an outward expanding circle. After a certain period of time, the particles will enter the "free fall" stage, that is, due to gravity, they begin to fall to the ground, just like fireworks that bloom and go out.
Basics: designing fireworks with Python and Tkinter

There is no longer a brain to throw out all the mathematical knowledge. We talk about theory while writing code. First of all, make sure you have installed and imported Tkinter, which is the standard GUI Library of Python. It is widely used in various projects and program development. Using Tkinter in Python can quickly create GUI applications

Basics: Design fireworks in Python and 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

In addition to Tkinter, in order to make the interface have a beautiful background, we also import PIL for image processing and other packages, such as time, random and math. They can make it easier for us to control the trajectory of fireworks particles.

The basic settings of Tkinter application are as follows:

root = tk.Tk()

In order to initialize Tkinter, we must create a Tk() root widget, which is a window with a title bar and other decorations provided by the window manager. The root part must be created before we create other widgets, and there can only be one root part.

w = tk.Label(root, text="Hello Tkinter!")

This line of code contains the Label part. The first parameter in the Label call is the name of the parent window, which is the "root" we use here. The keyword parameter "text" indicates the displayed text content. You can also call other widgets: Button, Canvas, etc.

w.pack()
root.mainloop()

The next two lines of code are important. The packaging method here is to tell Tkinter to resize the window to fit the widget used. The window is closed until we enter the Tkinter event loop Only appears when mainloop() is called. The script will stay in the event loop until we close the window.

Translate fireworks into code

Now let's design an object to represent each particle in the fireworks event. Each particle has some important attributes that govern its appearance and movement: size, color, position, speed, and so on.

'''
particles class
 Particles are randomly generated in the air, turn into a circle, fall and disappear
 attribute:
- id: Particle id
- x, y: Coordinates of particles
- vx, vy: Speed of change in coordinates
- total: total
- age: Duration of particle existence
- color: colour
- cv: canvas
- lifespan: Maximum duration
'''
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

If we go back to the original idea, we will realize that we must ensure that all particles in each fireworks bloom must go through three different stages, namely "expansion", "falling" and "disappearance". So we add some motion functions to the particle class, as shown below:

'''
def update(self, dt):
# Particle expansion 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)
# Fall with free fall
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
# If the particle's life cycle has passed, remove it
elif self.cid is not None:
 cv.delete(self.cid)
self.cid = None

Of course, this also means that we must define how long each particle blooms and falls. In this part, we need to try more parameters to achieve the best visual effect.

# Defines the time frame for the inflation effect
def expand (self):
return self.age <= 1.2
# Check whether the particles are still in the life cycle
def alive(self):
return self.age <= self.lifespan

3, Using Tkinter simulation

Now we conceptualize the movement of particles, but obviously, a fireworks can't have only one particle, and a fireworks show can't have only one fireworks. Our next step is to let Python and Tkinter continuously "emit" particles into the sky in a way we can control.

Here, we need to upgrade from operating one particle to displaying multiple fireworks and multiple particles in each fireworks on the screen.

Our solution is as follows: create a list, and each sub list is a fireworks, which contains a list of particles. The examples in each list have the same X and Y coordinates, size, color and initial speed.

numb_explode = randint(6,10)
# Create a list of all particles that simulate a fireworks bloom
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)

Our next step is to ensure that the particle's attributes are updated regularly. Here, we set the particles to update their state every 0.01 seconds and stop updating after 1.8 seconds (which means that the existence time of each particle is 1.6 seconds, of which 1.2 seconds is in the "blooming" state, 0.4 seconds is in the "falling" state, and 0.2 seconds is in the edge state before Tkinter completely removes it).

total_time = .0
# Keep updated within 1.8 second time frame
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

Now, we just need to combine the last two gist s into a function that can be called by Tkinter, and call it simulate(). This function will display all data items and update the properties of each data item according to the time we set. In our main code, we will call this function with an alarm processing module after(), and after() will wait for a certain time before calling the function.

We set Tkinter to wait for 100 units (1 second) and then call simulate.

if __name__ == '__main__':
 root = tk.Tk()
 cv = tk.Canvas(root, height=600, width=600)
 # Draw a black background
 cv.create_rectangle(0, 0, 600, 600, fill="black")
 cv.pack()
 root.protocol("WM_DELETE_WINDOW", close)
 # stimulate() is not called until 1 second later
 root.after(100, simulate, cv)
 root.mainloop()

OK, so we put on a fireworks show with Python code:

This article is only a simple version. After getting more familiar with Tkinter, you can also add more color and more beautiful background photos to let the code bloom more beautiful fireworks for you!

4, All codes

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
# Simulated gravity
GRAVITY = 0.05
# Color options (random or sequential)
colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen', 'indigo', 'cornflowerblue']
'''
particles class
 Particles are randomly generated in the air, turn into a circle, fall and disappear
 attribute:
 - id: Particle id
 - x, y: Coordinates of particles
 - vx, vy: Speed of change in coordinates
 - total: total
 - age: Duration of particle existence
 - color: colour
 - cv: canvas
 - lifespan: Maximum duration
'''
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
  # Particle range expansion
  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)
  # Fall with free fall
  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
  # Remove particles that exceed the maximum duration
  elif self.cid is not None:
   cv.delete(self.cid)
   self.cid = None
 # Expanded time
 def expand (self):
  return self.age <= 1.2
 # Is the particle within the maximum lifetime
 def alive(self):
  return self.age <= self.lifespan
'''
The loop call keeps going
'''
def simulate(cv):
 t = time()
 explode_points = []
 wait_time = randint(10, 100)
 numb_explode = randint(6, 10)
 # Create a two-dimensional list of all particles expanded at the same time
 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
 # Continuously expanded within 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
 # Loop call
 root.after(wait_time, simulate, cv)
def close(*ignore):
 """Exit the program and close the window"""
 global root
 root.quit()
if __name__ == '__main__':
 root = tk.Tk()
 cv = tk.Canvas(root, height=400, width=600)
 # Choosing a nice background will make the effect more amazing!
 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()

References link: python fireworks source code

Topics: Python Back-end Tkinter