Inadvertently see a paragraph with Tkinter Library written fireworks program , Just followed .

Design concept : By splitting a particle on the picture into X Number of particles to simulate the explosion effect . Particles can occur " expand ”, It means that they will move at a constant speed and have 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 time , Particles will enter " Free fall ” stage , That is, because of gravity, they began to fall to the ground , Like fireworks that go out after blooming .

First, we write a particle class , Represents each particle in a fireworks event , Include size , colour , position , Properties such as velocity and functions of the three stages experienced by particles , Namely : expand , fall , disappear .

'''

particles class

Particles are randomly generated in the air , Become a circle , Fall , 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 = 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

# 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

Next we need to create a list , Each sublist is a fireworks , It contains a list of particles , Particles in each list have the same x,y coordinate , size , colour , Initial speed .

The source code is as follows :

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 in order )

colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple',
'seagreen', 'indigo', 'cornflowerblue']

'''

particles class

Particles are randomly generated in the air , Become a circle , Fall , 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 = 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

# 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

# 1.8s Has been expanding within

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 program , close window """

global root

root.quit()

if __name__ == '__main__':

root = tk.Tk()

cv = tk.Canvas(root, height=360, width=480)

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

design sketch ( Please ignore the background ):

The above is the whole content of this article , I hope it will be helpful to your study , I also hope you can support the script house .

Technology