用Python看今年的第一场烟花

586 阅读3分钟

前几天微信更新了版本,增加了烟花的表情,有XM同学提出建议,运用python编程实现烟花的效果。正值2021春节到来之际,祝大家2021春节愉快,祝我们的祖国繁荣昌盛!

**Gif制作:**https://en.softonic.com/best/free-to-play-games/?utm_source=wakeup

视频链接:

一.知识介绍

1.tkinter:这个小项目的主角,是一个python图形模块。且Python3已经自带了该模块,不用另外安装。它有点像java中的swing图形模块(由众多组件集成,组件通过创建实例添加,组件通过坐标定位在窗口上)。

2.PIL:Python Imaging Library,是Python平台的图像处理标准模块。在Python3也是自带的,在这个项目中用于背景图片的导入。

3.time:相信这个模块大家都不会陌生,导入它用来控制烟花的绽放,坠落及消失时间。

4.random:随机数模块,用于生成烟花随机坐标点,随机绽放速度,随机消失时间。

5.math:这个模块大家应该也很熟悉了,导入它的目的是使烟花绽放的粒子以一定角度散开。

二.完整代码

# -*- coding: utf-8 -*-"""Spyder EditorThis is a temporary script file.""" '''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 background image)*The design is based on high school physics, with some small twists only for aesthetics purpose'''import tkinter as tk# from tkinter import messagebox# from tkinter import PhotoImagefrom PIL import Image, ImageTk ,ImageDrawfrom time import time, sleepfrom random import choice, uniform, randintfrom math import sin, cos, radiansfrom PIL import ImageFont # gravity, act as our constant g, you can experiment by changing itGRAVITY = 0.05# list of color, can choose randomly or use as a queue (FIFO)colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple',           'red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple','seagreen', 'indigo', 'cornflowerblue']  '''Generic class for particlesparticles are emitted almost randomly on the sky, forming a round of circle (a star) before falling and getting removedfrom canvasAttributes:    - id: identifier of a particular particle in a star    - x, y: x,y-coordinate of a star (point of explosion)    - vx, vy: speed of particle in x, y coordinate    - total: total number of particle in a star    - age: how long has the particle last on canvas    - color: self-explantory    - cv: canvas    - lifespan: how long a particle will last on canvas'''  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 expansions        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)         # falling down in projectile motion        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 article if it is over the lifespan        elif self.cid is not None:            cv.delete(self.cid)            self.cid = None     # define time frame for expansion    def expand(self):        return self.age <= 1.2     # check if particle is still alive in lifespan    def alive(self):        return self.age <= self.lifespan  '''Firework simulation loop:Recursively call to repeatedly emit new fireworks on canvasa list of list (list of stars, each of which is a list of particles)is created and drawn on canvas at every call, via update protocol inside each 'part' object '''  def simulate(cv):    t = time()    explode_points = []    wait_time = randint(10, 100)        numb_explode = randint(6, 10)    # create list of list of all particles in all simultaneous explosion    # 创建一个所有粒子同时扩大的二维列表    for point in range(numb_explode):        objects = []        x_cordi = randint(50, 1250)        y_cordi = randint(50, 500)#        烟花降落的速度        speed = uniform(1, 4)        size = uniform(0.5, 3)        color = choice(colors)        explosion_speed = uniform(1.5, 6)        total_particles = randint(20, 100)        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    # keeps undate within a timeframe of 1.8 second    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    # recursive call to continue adding new explosion on canvas    root.after(wait_time, simulate, cv)  def close(*ignore):    """Stops simulation loop and closes the window."""    global root    root.quit()  if __name__ == '__main__':            root = tk.Toplevel()    root.title("2021新年快乐呀^_^")        cv = tk.Canvas(root, height=854, width=1280)            # use a nice background image#    image = Image.open("image1.jpg")#    photo = ImageTk.PhotoImage(image)#        #设置字体,如果没有,也可以不设置    font = ImageFont.truetype("C:\\Windows\\Fonts\\simsun.ttc",60)    #现在是宋体    #打开底版图片    image=Image.open("image1.jpg")    # 在图片上添加文字 1    draw = ImageDraw.Draw(image)    draw.text((400, 50),"2021要加油哦",fill = "yellow",font=font)#    draw = ImageDraw.Draw(image)    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()

三 参考文献

  1. 代码参考链接:github.com/tuangauss/D…
  2. python 图片上添加文字:blog.csdn.net/dyyay521/ar…
  3. 【解决问题】Python-Error:image "pyimage1" doesn't exist:blog.csdn.net/weixin_4443…