目录
- 效果展示
- 实现代码
- 剩下代码
跨年倒计时还有18天?我已经开始整烟花了,虽然不是很好看吧,但是也能将就看看 😥
这个的背景图,音乐,还有文字都是可以自己修改的哦
效果展示
依次导入本次需要使用到的模块
import random | |
import pygame as py | |
import tkinter as tk | |
from time import time, sleep | |
from tkinter import filedialog | |
from PIL import Image, ImageTk | |
from math import sin, cos, radians | |
from random import choice, uniform, randint |
实现代码
生成随机颜色
def randomcolor(): | |
#生成随机颜色 | |
colArr = ['','2','3','4','5','6','7','8','9','A','B','C','D','E','F'] | |
color = "" | |
for i in range(): | |
color += colArr[random.randint(,14)] | |
return "#"+color | |
GRAVITY =.06 | |
colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen','indigo', 'cornflowerblue', 'pink'] | |
属性
Generic class for particles | |
particles are emitted almost randomly on the sky, forming a round of circle (a star) before falling and getting removed | |
from canvas | |
Attributes(属性): | |
- id: 粒子的id | |
- x, y: 粒子的坐标 | |
- vx, vy: 粒子在对应坐标的变化速度 | |
- total:一颗烟花里的粒子总数 | |
- age: 粒子在画布上停留的时间 | |
- color: 自我移植 | |
- cv: 画布 | |
- lifespan: 粒子在画布上停留的时间 |
粒子运动的速度
这个里面的新年快乐是可以自己更改的哦
class part: | |
#为每一个烟花绽放出来的粒子单独构建一个类的对象 ,每个粒子都会有一些重要的属性,决定它的外观(大小、颜色)、移动速度等 | |
def __init__(self, cv, idx, total, explosion_speed, x=., y=0., vx = 0., vy = 0., size=3., color = 'red', lifespan = 2, **kwargs): | |
self.id = idx | |
#每个烟花的特定标识符 | |
self.x = x | |
#烟花绽放x轴 | |
self.y = y | |
#烟花绽放y轴 | |
self.initial_speed = explosion_speed | |
#粒子初始速度 | |
self.vx = vx | |
#粒子运动x轴速度 | |
self.vy = vy | |
#粒子运动y轴速度 | |
self.total = total | |
#绽放粒子数 | |
self.age = | |
#粒子已停留时间 | |
self.color = color | |
#粒子颜色 | |
self.cv = cv | |
#画布 | |
self.cid = self.cv.create_oval(x - size, y - size, x + size,y + size, fill=self.color, outline='white',width=.01) | |
#指定一个限定矩形(Tkinter 会自动在这个矩形内绘制一个椭圆) | |
self.lifespan = lifespan | |
#粒子在画布上停留的时间 |
xy轴移动位移
如果粒子仅存活不扩张(只是停留时间足够,说明膨胀到最大了),则自由坠落
elif self.alive(): | |
columnFont = ('华文行楷',) | |
self.cv.create_text(, 100, text='新',tag="write_tag", fill=choice(colors),font = columnFont) #字体 | |
self.cv.create_text(, 100, text='年',tag="write_tag", fill=choice(colors),font = columnFont) | |
self.cv.create_text(, 100, text='快',tag="write_tag", fill=choice(colors),font = columnFont) | |
self.cv.create_text(, 100, text='乐',tag="write_tag", fill=choice(colors),font = columnFont) | |
#删除文字标签 | |
move_x = cos(radians(self.id*/self.total)) | |
#x轴的移动位移 | |
# 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 | |
#更新y轴 |
膨胀效果时间帧
判断膨胀时间是否小于1.2秒
def expand (self): | |
#定义膨胀效果时间帧 | |
return self.age <=.2 |
判断粒子是否仍在生命周期内
判断已停留时间是否小于应该停留时间
def alive(self): | |
#判断粒子是否仍在生命周期内 | |
return self.age <= self.lifespan |
剩下代码
不想一步步写出来咯,有点麻烦哈哈
代码后面都有注释哈
def simulate(cv): | |
t = time() | |
#返回自年后经过的浮点秒数,精确到小数点后7位 | |
explode_points = [] | |
#爆炸点列表,烟花列表 | |
wait_time = randint(,100) | |
#等待时间为到100之间整数 | |
numb_explode = randint(,20) | |
#爆炸烟花个数时到10之间的随机整数 | |
# create list of list of all particles in all simultaneous explosion | |
for point in range(numb_explode): | |
#为所有模拟烟花绽放的全部粒子创建一列列表 | |
if point<=: | |
objects = [] | |
#每个点的爆炸粒子列表粒子列表 | |
x_cordi = + point*50 | |
#每个爆炸点的x轴 | |
y_cordi = | |
#每个爆炸点的y轴 | |
speed = uniform (.5, 2.5) | |
#每个爆炸点的速度 | |
size = uniform (.5,3) | |
#每个爆炸点的大小 | |
color = choice(colors) | |
#每个爆炸点的颜色 | |
explosion_speed = uniform(.6, 3) | |
#爆炸的绽放速度 | |
total_particles = randint(,60) | |
#烟花的总粒子数 | |
for i in range(,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(.6,1.75)) | |
#把上述参数代入part函数,但是每个粒子的生存时间是自己独立的 | |
objects.append(r) | |
#把r添加进粒子列表 | |
explode_points.append(objects) | |
#把粒子列表添加进烟花列表 | |
else: | |
objects = [] | |
#每个点的爆炸粒子列表粒子列表 | |
x_cordi = randint(,550) | |
#每个爆炸点的x轴 | |
y_cordi = randint(, 250) | |
#每个爆炸点的y轴 | |
speed = uniform (.5, 2.5) | |
#每个爆炸点的速度 | |
size = uniform (.5,3) | |
#每个爆炸点的大小 | |
color = choice(colors) | |
#每个爆炸点的颜色 | |
explosion_speed = uniform(.3, 2) | |
#爆炸的绽放速度 | |
total_particles = randint(,50) | |
#烟花的总粒子数 | |
for i in range(,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(.6,1.75)) | |
#把上述参数代入part函数,但是每个粒子的生存时间是自己独立的 | |
objects.append(r) | |
#把r添加进粒子列表 | |
explode_points.append(objects) | |
#把粒子列表添加进烟花列表 | |
total_time = . | |
#初始化总时间 | |
# keeps undate within a timeframe of.8 second | |
while total_time <: | |
#当总时间小于.8秒时运行该循环 | |
sleep(.03) | |
#让画面暂停.01秒 | |
tnew = time() | |
#刷新时间 | |
t, dt = tnew, tnew - t | |
#时间等于新时间,和上次时间间隔为tnew-t | |
for point in explode_points: | |
#遍历烟花列表 | |
for item in point: | |
#遍历烟花里的粒子列表 | |
item.update(dt) | |
#粒子更新时间 | |
cv.update() | |
#刷新画布 | |
total_time += dt | |
#为while循环增加时间 | |
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.Tk() | |
root.title('新年快乐~~') # 设置窗体的标题栏 | |
cv = tk.Canvas(root, height=, width=600) | |
#绘制一个高,宽600的画布 | |
bgpath = filedialog.askopenfilename(title='请选择背景图片') | |
#选择背景图片 | |
image = Image.open(bgpath) | |
#打开背景图片 | |
image = image.resize((,600), Image.ANTIALIAS) | |
#把背景图片调整成窗口大小 | |
photo = ImageTk.PhotoImage(image) | |
cv.create_image(, 0, image=photo, anchor='nw') | |
#在画布上绘制加载的背景图片 | |
bgmusic = filedialog.askopenfilename(title='请选择背景音乐') | |
py.mixer.init() | |
# 初始化 | |
py.mixer.music.load(bgmusic) | |
# 文件加载 | |
py.mixer.music.play(-, 0, fade_ms=50) | |
# 播放 第一个是播放值 -代表循环播放, 第二个参数代表开始播放的时间 | |
py.mixer.music.pause() | |
#暂停 | |
py.mixer.music.unpause() | |
#取消暂停 | |
cv.pack() | |
#把cv添加进去 | |
root.protocol("WM_DELETE_WINDOW", close) | |
root.after(, simulate, cv) | |
#在.1秒后再调用stimulate函数,生成一轮烟花绽放效果 | |
root.mainloop() | |
#执行root,生成窗口 |