Pour ceux d'entre vous qui tapent du code tous les jours, avez-vous déjà pensé que le code pouvait aussi devenir cool et romantique ? Aujourd'hui, je vais vous apprendre à utiliser Python pour simuler des feux d'artifice en fleurs. Vous pouvez également laisser le programme déclencher un feu d'artifice pour vous à tout moment après le travail.
code source de confession de feux d'artifice cool python
Ce petit projet intéressant n'est pas compliqué, juste un peu de compétences en visualisation, 100 avec juste quelques lignes de code Python et la librairie Tkinter, on peut enfin obtenir l'effet suivant :
Après avoir terminé ce tutoriel, vous pouvez également créer un tel feu d'artifice.
Revue globale du concept
L'ensemble de notre concept est relativement simple.
Comme le montre l'image ci-dessus, nous simulons l'effet d'explosion en divisant une particule sur l'écran en un nombre X de particules. Les particules « se dilatent », ce qui signifie qu’elles se déplacent à une vitesse constante et à des angles égaux les unes par rapport aux autres. Cela nous permettra de simuler un feu d'artifice sous la forme d'un cercle en expansion. Après un certain temps, les particules entrent dans une phase de « chute libre », où elles commencent à tomber au sol sous l'effet de la gravité, comme des feux d'artifice qui s'épanouissent puis s'éteignent.
(Apprentissage recommandé : Cours d'apprentissage en programmation)
Connaissances de base : Concevoir des feux d'artifice avec Python et Tkinter
Pas plus ici Jetez toutes les connaissances mathématiques d’un coup, et nous parlons de théorie en écrivant du code. Tout d'abord, assurez-vous d'installer et d'importer Tkinter, qui est la bibliothèque GUI standard de Python et qui est largement utilisée dans une variété de projets et de développement de programmes. L'utilisation de Tkinter dans Python peut créer rapidement des applications GUI.
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
En plus de Tkinter, afin de donner à l'interface un beau fond, nous importons également PIL pour le traitement d'image, ainsi que d'autres packages, comme time, random et math. Ils nous permettent de contrôler plus facilement la trajectoire des particules des feux d’artifice.
La configuration de base de l'application Tkinter est la suivante :
root = tk.Tk()
Afin d'initialiser Tkinter, nous devons créer un widget racine Tk(), qui est une fenêtre avec une barre de titre et d'autres décorations fournies par le gestionnaire de fenêtres. Ce widget racine doit être créé avant de créer d’autres widgets, et il ne peut y avoir qu’un seul widget racine.
w = tk.Label(root, text="Hello Tkinter!")
Cette ligne de code contient le composant Label. Le premier paramètre de l'appel Label est le nom de la fenêtre parent, qui est la "racine" que nous utilisons ici. L'argument mot-clé "text" spécifie le contenu du texte à afficher. Vous pouvez également appeler d'autres widgets : Button, Canvas, etc.
w.pack() root.mainloop()
Les deux lignes de code suivantes sont importantes. La méthode de packaging ici consiste à dire à Tkinter de redimensionner la fenêtre pour l'adapter au widget utilisé. La fenêtre n'apparaîtra pas tant que nous n'entrerons pas dans la boucle d'événements Tkinter et qu'elle ne sera pas appelée par root.mainloop(). Le script restera dans la boucle d'événements jusqu'à ce que nous fermions la fenêtre.
Traduire le feu d'artifice en code
Nous concevons maintenant un objet pour représenter chaque particule du feu d'artifice. Chaque particule possède des propriétés importantes qui régissent son apparence et son mouvement : taille, couleur, position, vitesse, etc.
''' particles 类 粒子在空中随机生成随机,变成一个圈、下坠、消失 属性: - id: 粒子的id - x, y: 粒子的坐标 - vx, vy: 在坐标的变化速度 - total: 总数 - age: 粒子存在的时长 - color: 颜色 - cv: 画布 - lifespan: 最高存在时长 ''' 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 = 0self.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
Si l'on repense à l'idée originale, on se rendra compte qu'il faut faire en sorte que toutes les particules de chaque feu d'artifice doivent passer par 3 étapes différentes, à savoir "expansion", "chute" et "disparition" . Nous ajoutons donc quelques fonctions de mouvement supplémentaires à la classe de particules, comme indiqué ci-dessous :
def update(self, dt): # 粒子膨胀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.vx = move_x/(float(dt)*1000) self.vy = move_y/(float(dt)*1000) self.cv.move(self.cid, move_x, move_y) # 以自由落体坠落 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 # 如果粒子的生命周期已过,就将其移除 elif self.cid is not None: cv.delete(self.cid) self.cid = None
Bien sûr, cela signifie également que nous devons définir la durée pendant laquelle chaque particule fleurit et combien de temps elle tombe. Cette partie nous oblige à essayer quelques paramètres supplémentaires pour obtenir le meilleur effet visuel.
# 定义膨胀效果的时间帧 def expand (self): return self.age <= 1.2 # 检查粒子是否仍在生命周期内 def alive(self): return self.age <= self.lifespan
Utilisation de la simulation Tkinter
Maintenant, nous conceptualisons le mouvement des particules, mais il est évident qu'un feu d'artifice ne peut pas avoir qu'une seule particule, et qu'un feu d'artifice ne peut pas avoir seulement un feu d'artifice. Notre prochaine étape consiste à laisser Python et Tkinter « tirer » continuellement des particules dans le ciel d’une manière que nous pouvons contrôler.
À ce stade, nous devons passer de l'exploitation d'une particule à l'affichage de plusieurs feux d'artifice et de plusieurs particules dans chaque feu d'artifice sur l'écran.
Notre solution est la suivante : créez une liste, chaque sous-liste est un feu d'artifice, qui contient une liste de particules. Les exemples de chaque liste ont les mêmes coordonnées x, y, taille, couleur et vitesse initiale.
numb_explode = randint(6,10) # 为所有模拟烟花绽放的全部粒子创建一列列表 for point in range(numb_explode): objects = [] x_cordi = randint(50,550) y_cordi = randint(50, 150) 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, color=color, size = size, lifespan = uniform(0.6,1.75)) objects.append(r) explode_points.append(objects)
Notre prochaine étape consiste à nous assurer que les propriétés des particules sont mises à jour régulièrement. Ici, nous configurons les particules pour qu'elles mettent à jour leur statut toutes les 0,01 seconde et arrêtent la mise à jour après 1,8 seconde (cela signifie que chaque particule existe pendant 1,6 seconde, dont 1,2 seconde est l'état "floraison" et 0,4 seconde est l'état "chute". 0,2 seconde sur le bord avant que Tkinter ne le supprime complètement).
total_time = .0 # 在1.8秒时间帧内保持更新 while total_time < 1.8: sleep(0.01) tnew = time() t, dt = tnew, tnew - t for point in explode_points: for part in point: part.update(dt) cv.update() total_time += dt
现在,我们只需将最后两个gist合并为一个能被Tkinter调用的函数,就叫它simulate()吧。该函数会展示所有的数据项,并根据我们设置的时间更新每个数据项的属性。在我们的主代码中,我们会用一个alarm处理模块after()调用此函数,after()会等待一定的时间,然后再调用函数。
我们这里设置让Tkinter等待100个单位(1秒钟)再调取simulate。
if __name__ == '__main__': root = tk.Tk() cv = tk.Canvas(root, height=600, width=600) # 绘制一个黑色背景 cv.create_rectangle(0, 0, 600, 600, fill="black") cv.pack() root.protocol("WM_DELETE_WINDOW", close) # 在1秒后才开始调用stimulate() root.after(100, simulate, cv) root.mainloop()
好了,这样我们就用Python代码放了一场烟花秀:
本文只一个简单版本,等进一步熟悉Tkinter后,还可以添加更多颜色更漂亮的背景照片,让代码为你绽放更美的烟花!
以下是全部代码:
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 # 模拟重力 GRAVITY = 0.05 # 颜色选项(随机或者按顺序) colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen', 'indigo', 'cornflowerblue'] ''' particles 类 粒子在空中随机生成随机,变成一个圈、下坠、消失 属性: - id: 粒子的id - x, y: 粒子的坐标 - vx, vy: 在坐标的变化速度 - total: 总数 - age: 粒子存在的时长 - color: 颜色 - cv: 画布 - lifespan: 最高存在时长 ''' 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 = 0self.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 # 粒子范围扩大 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) # 以自由落体坠落 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 # 移除超过最高时长的粒子 elif self.cid is not None: cv.delete(self.cid) self.cid = None # 扩大的时间 def expand (self): return self.age <= 1.2 # 粒子是否在最高存在时长内 def alive(self): return self.age <= self.lifespan ''' 循环调用保持不停 ''' def simulate(cv): t = time() explode_points = [] wait_time = randint(10, 100) numb_explode = randint(6, 10) # 创建一个所有粒子同时扩大的二维列表 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内一直扩大 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 # 循环调用 root.after(wait_time, simulate, cv) def close(*ignore): """退出程序、关闭窗口""" global root root.quit() if __name__ == '__main__': root = tk.Tk() cv = tk.Canvas(root, height=400, width=600) # 选一个好看的背景会让效果更惊艳! 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()
众多python培训视频,尽在python学习网,欢迎在线学习!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!