-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
185 lines (151 loc) · 5.73 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# -*- coding: utf-8 -*-
"""
Spyder Editor
This 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 PhotoImage
from PIL import Image, ImageTk ,ImageDraw
from time import time, sleep
from random import choice, uniform, randint
from math import sin, cos, radians
from PIL import ImageFont
# gravity, act as our constant g, you can experiment by changing it
GRAVITY = 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 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: 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 canvas
a 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("FROM FTI WITH LOVE^_^")
cv = tk.Canvas(root, height=800, width=564)
# use a nice background image
# image = Image.open("image1.jpg")
# photo = ImageTk.PhotoImage(image)
#
#设置字体,如果没有,也可以不设置
font = ImageFont.truetype("AppleGaramond-Light.ttf",30) #现在是宋体
#打开底版图片
image=Image.open("image1.jpeg")
# 在图片上添加文字 1
draw = ImageDraw.Draw(image)
draw.text((50, 270),"May 2022 bring you peace, joy, and happiness",fill = "red",font=font)
bottom = ImageDraw.Draw(image)
bottom.text((230, 580),"Tuan Luong",fill = "red",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()