Tanabata Festival is coming soon. Those with objects and those without objects must be magical. Make a fireworks show in Python

Posted by bigbob on Sun, 26 Dec 2021 08:01:29 +0100

Today is Wednesday, and there are three days left for Tanabata Festival. I'm afraid it's too late to buy gifts for my girlfriend!

Then what shall I do? Then prepare a fireworks video for her.

But not everyone can set off fireworks in the whole city except local tyrants. I can only think about an ordinary one. Although the dream is far away, I haven't given up yet. I decided to use Python to help me realize this wish. After all, Python is omnipotent.

The following is the dynamic effect of fireworks implemented in Python.

Tkinter and code implementation

This dynamic effect is completed by Tkinter library and belongs to the GUI programming part of Python. Python provides several libraries of graphical development interfaces, including Tkinter, xwPython and Jython. Tkinter is a standard GUI library for Python. It is built in Python and does not need additional installation. It can be easily implemented for some simple graphical interfaces.

The following is the code implementation of the fireworks effect of Tanabata Festival. First, import all the required libraries:

  • Tkinter: final GUI implementation;
  • PIL: process the image and use it in the last canvas background;
  • Time: processing time to complete the update iteration of the time life cycle;
  • Random: randomly generated number, which defines the random variable in the discharge process;
  • math: mathematical function method to calculate the mobile use of discharge;
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 Copy code

Then define a general fireworks particle class (part). The properties of fireworks particles are as follows:

  • id: identification of particles in each fireworks;
  • x. y: x, y axis of fireworks;
  • vx, vy: velocity of particles in the x, y axis;
  • total: number of particles of each fireworks;
  • age: the time the particle has spent in the background;
  • Color: color;
  • cv: background;
  • lifespan: how long the particles will last in the background;

Then, some class methods of fireworks particles are defined in this class:

  • Update: update the life time of particles by judging the particle status;
  • expand: defines the time of explosion;
  • alive: check whether particles still exist in the life cycle;
# Set gravity parameters
GRAVITY = 0.05
# Set random color list
colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen', 'indigo', 'cornflowerblue']

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 = 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 explosion
        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)

        # Particle falling
        elif self.alive():
            move_x = cos(radians(self.id * 360 / self.total))
     
            self.cv.move(self.cid, self.vx + move_x, self.vy + GRAVITY * dt)
            self.vy += GRAVITY * dt

        # If the particle exceeds the maximum duration, the particle disappears
        elif self.cid is not None:
            cv.delete(self.cid)
            self.cid = None

    # Define the time of the explosion
    def expand(self):
        return self.age <= 1.2

    # Check whether the particles still exist in the life cycle
    def alive(self):
        return self.age <= self.lifespan Copy code

After completing the implementation of a general fireworks particle class above, let's start the simulation cycle process of fireworks discharge: generate new fireworks in the background through recursion.

First, define a simulate simulated function, and set some parameters in the function:

  • t: Time stamp;
  • explode_points: list of fireworks explosion points for subsequent updates;
  • num_explore: random number of fireworks;

Then create all fireworks particle classes in a cycle of all fireworks quantities. Of course, in each cycle, the particle class needs to set certain attribute parameters, most of which are generated randomly:

  • Objects: store all granular objects;
  • x_cordi,y_cordi: X and Y coordinate positions of randomly generated fireworks in the background (50550);
  • Speed: randomly generated particle moving speed (0.5, 1.5);
  • Size: randomly generated particle size (0.5, 3);
  • Color: select the color in the random list of colors;
  • total_particles: the number of all particles in each fireworks randomly generated;

With these parameters, we can define the cycle to generate each particle object, and store all particle objects of each fireworks in objects. That is, explore_points is a set of lists in the list, the inner list is all particle objects of each fireworks, and the outer list is all fireworks.

After all particle objects are completed, the life time of each particle is updated, and the total time is set within 1.8 seconds. Finally, through root recursion, the fireworks can be set off in the background all the time.

def simulate(cv):
    t = time()
    explode_points = []
    wait_time = randint(10, 100)
    numb_explode = randint(6, 10)
    # Cycle to create all fireworks particles
    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 = part(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
    # Keep updating within 1.8 seconds
    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
    # Continuously add new fireworks to the background through recursion
    root.after(wait_time, simulate, cv)

def close(*ignore):
    """Stop the simulation cycle and close the window"""
    global root
    root.quit()Copy code

The above code part has nothing to do with Tkinter, but defines the particle object and the whole process of simulating the particle life cycle. Tkinter will be used to complete the final effect below.

  • root: object of Tkinter class;
  • cv: defines the background canvas object in Tkinter, where the height and width parameters can be adjusted according to the actual situation;
  • Image: open the image object. The image will be used as the background in the canvas. The image can be selected according to your preferences;
  • photo: use ImageTk to define the image object in Tkinter;

Then create an image on the canvas object (using the defined photo object as a parameter), and finally call the Tkinter object root to continue the simulate simulation process.

if __name__ == '__main__':
    root = tk.Tk()
    cv = tk.Canvas(root, height=600, width=600)
    # Choose a good image background to fill the canvas
    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()Copy code
Note: the background picture can be changed according to your preference. You don't need to customize your own fireworks show

Dry goods mainly include:

① More than 2000 Python e-books (both mainstream and classic books should be available)

② Python standard library materials (the most complete Chinese version)

③ Project source code (forty or fifty interesting and classic hand training projects and source code)

④ Videos on basic introduction to Python, crawler, web development and big data analysis (suitable for Xiaobai)

⑤ Python learning roadmap (bid farewell to non stream learning)

⑥ Two days of Python crawler training camp live rights

If you need it, you can get it from the little fat man~


 

 

Topics: Python Django list Tornado virtualenv