Введение
В ходе данной статьи напишем код для красивой анимации запуска и взрыва фейерверков на Python с использованием библиотеки Tkinter.
Настройка окна приложения
Для начала импортируем tkinter, random и math:
import tkinter as tk
import random
import math
Создадим окно приложения с размерами 800×600 и чёрным фоном, которое будет служить нашим «ночным небом»:
import tkinter as tk
import random
import math
# Настройка окна
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
# Запуск основного цикла приложения
root.mainloop()
Создадим холст для рисования:
import tkinter as tk
import random
import math
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
# Холст для рисования
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Создание ракеты
Добавим функцию для запуска ракеты, которую назовём create_rocket(). Внутри неё первым делом определим случайную горизонтальную позицию, нижнюю стартовую позицию, конечную позицию и отрисуем овал:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700) # Случайная горизонтальная позиция
y_start = 600 # Стартовая позиция снизу
y_target = random.randint(100, 300) # Конечная позиция (высота взрыва)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Далее создадим вложенную функцию animate_rocket() для анимации взлёта. Внутри неё используем ключевое слово nonlocal для доступа к переменной y_start из внешней функции:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
# Анимация взлёта
def animate_rocket():
nonlocal y_start
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Следом будет идти условие, что если текущая позиция y_start больше конечной позиции y_target, ракета продолжает двигаться вверх:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
# Анимация взлета
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10) # Двигаем ракету вверх
y_start -= 10
root.after(30, animate_rocket) # Запускаем следующий кадр
else:
canvas.delete(rocket) # Удаляем ракету после достижения цели
animate_rocket()
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Реализация взрыва
Теперь добавим эффект взрыва. Для этого у нас будет служить функция explode().
У функции будет присутствовать два параметра, а именно:
- x — координата по X центра взрыва, которая определяет, где по горизонтали начнется анимация (центр, откуда разлетаются частицы).
- y_target — координата по Y центра взрыва, которая определяет, где по вертикали начнется анимация (центр, откуда разлетаются частицы).
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10)
y_start -= 10
root.after(30, animate_rocket)
else:
canvas.delete(rocket)
animate_rocket()
# Реализация взрыва
def explode(x, y_target):
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Внутри функции сначала будет идти список colors с цветами и пустой список particles, предназначенный для хранения данных о частицах взрыва. Далее будет идти цикл, в котором будет создаваться 30 частиц со случайными углами направления, дистанцией разлёта, смещением по оси X и Y и со случайными цветами:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10)
y_start -= 10
root.after(30, animate_rocket)
else:
canvas.delete(rocket)
animate_rocket()
def explode(x, y_target):
# Функция создает взрыв в виде разноцветных частиц
colors = ["red", "orange", "yellow", "green", "blue", "purple", "white"]
# Список цветов для частиц взрыва
particles = [] # Список для хранения данных о частицах
for _ in range(30): # Создаем 30 частиц взрыва
angle = random.uniform(0, 360) # Случайный угол (в градусах) для направления
distance = random.uniform(20, 100) # Случайная дистанция разлета
dx = distance * math.cos(angle) # Расчет смещения по оси X
dy = distance * math.sin(angle) # Расчет смещения по оси Y
color = random.choice(colors) # Случайный выбор цвета из списка
particle = canvas.create_oval(
x, y_target, x + 5, y_target + 5, fill=color, outline=color
) # Создаем частицу как цветной круг на холсте
particles.append((particle, dx, dy)) # Добавляем частицу в список
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Теперь добавим вложенную функцию animate_explosion() для анимации взрыва. Внутри неё будет находиться цикл, который пройдётся по всем данным из списка particles и реализует анимацию движения частиц взрыва:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10)
y_start -= 10
root.after(30, animate_rocket)
else:
canvas.delete(rocket)
animate_rocket()
def explode(x, y_target):
colors = ["red", "orange", "yellow", "green", "blue", "purple", "white"]
particles = []
for _ in range(30):
angle = random.uniform(0, 360)
distance = random.uniform(20, 100)
dx = distance * math.cos(angle)
dy = distance * math.sin(angle)
color = random.choice(colors)
particle = canvas.create_oval(
x, y_target, x + 5, y_target + 5, fill=color, outline=color
)
particles.append((particle, dx, dy))
# Анимация движения частиц взрыва
def animate_explosion():
for particle, dx, dy in particles:
# Перемещаем частицу в соответствии с расчетными смещениями
canvas.move(particle, dx * 0.1, dy * 0.1)
pos = canvas.coords(particle) # Получаем текущие координаты частицы
# Если частица вышла за пределы окна, удаляем её
if pos[0] < 0 or pos[1] < 0 or pos[2] > 800 or pos[3] > 600:
canvas.delete(particle)
particles.remove((particle, dx, dy))
# Если остались частицы, продолжаем анимацию
if particles:
root.after(50, animate_explosion)
animate_explosion() # Запускаем анимацию
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Объединение взлета ракеты и взрыва
Обновим функцию create_rocket(), чтобы вызывать explode() после завершения взлета:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10)
y_start -= 10
root.after(30, animate_rocket)
else:
canvas.delete(rocket)
explode(x, y_target)
animate_rocket()
def explode(x, y_target):
colors = ["red", "orange", "yellow", "green", "blue", "purple", "white"]
particles = []
for _ in range(30):
angle = random.uniform(0, 360)
distance = random.uniform(20, 100)
dx = distance * math.cos(angle)
dy = distance * math.sin(angle)
color = random.choice(colors)
particle = canvas.create_oval(
x, y_target, x + 5, y_target + 5, fill=color, outline=color
)
particles.append((particle, dx, dy))
def animate_explosion():
for particle, dx, dy in particles:
canvas.move(particle, dx * 0.1, dy * 0.1)
pos = canvas.coords(particle)
if pos[0] < 0 or pos[1] < 0 or pos[2] > 800 or pos[3] > 600:
canvas.delete(particle)
particles.remove((particle, dx, dy))
if particles:
root.after(50, animate_explosion)
animate_explosion()
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
root.mainloop()
Запуск нескольких фейерверков
Для автоматического запуска новых ракет добавим функцию start_fireworks(), которая будет вызывать create_rocket() каждые 1000 мс:
import tkinter as tk
import random
import math
def create_rocket():
x = random.randint(100, 700)
y_start = 600
y_target = random.randint(100, 300)
rocket = canvas.create_oval(x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white")
def animate_rocket():
nonlocal y_start
if y_start > y_target:
canvas.move(rocket, 0, -10)
y_start -= 10
root.after(30, animate_rocket)
else:
canvas.delete(rocket)
explode(x, y_target)
animate_rocket()
def explode(x, y_target):
colors = ["red", "orange", "yellow", "green", "blue", "purple", "white"]
particles = []
for _ in range(30):
angle = random.uniform(0, 360)
distance = random.uniform(20, 100)
dx = distance * math.cos(angle)
dy = distance * math.sin(angle)
color = random.choice(colors)
particle = canvas.create_oval(
x, y_target, x + 5, y_target + 5, fill=color, outline=color
)
particles.append((particle, dx, dy))
def animate_explosion():
for particle, dx, dy in particles:
canvas.move(particle, dx * 0.1, dy * 0.1)
pos = canvas.coords(particle)
if pos[0] < 0 or pos[1] < 0 or pos[2] > 800 or pos[3] > 600:
canvas.delete(particle)
particles.remove((particle, dx, dy))
if particles:
root.after(50, animate_explosion)
animate_explosion()
def start_fireworks():
create_rocket()
root.after(1000, start_fireworks)
root = tk.Tk()
root.title("Фейерверки!")
root.geometry("800x600")
root.configure(bg="black")
root.resizable(False, False)
canvas = tk.Canvas(root, width=800, height=600, bg="black", highlightthickness=0)
canvas.pack()
start_fireworks()
root.mainloop()
Итог. Фейерверки на Python
ООП версия. Фейерверки на Python
Тот же результат, но с использованием ООП:
import tkinter as tk
import random
import math
class FireworksApp:
def __init__(self, width=800, height=600):
self.width = width
self.height = height
# Настройка окна
self.root = tk.Tk()
self.root.title("Фейерверки!")
self.root.geometry(f"{width}x{height}")
self.root.configure(bg="black")
self.root.resizable(False, False)
# Холст для рисования
self.canvas = tk.Canvas(self.root, width=width, height=height, bg="black", highlightthickness=0)
self.canvas.pack()
def create_rocket(self):
x = random.randint(100, self.width - 100)
y_start = self.height
y_target = random.randint(100, 300)
rocket = self.canvas.create_oval(
x - 2, y_start - 10, x + 2, y_start + 10, fill="white", outline="white"
)
def explode():
self.canvas.delete(rocket)
colors = ["red", "orange", "yellow", "green", "blue", "purple", "white"]
particles = []
for _ in range(30):
angle = random.uniform(0, 2 * math.pi)
distance = random.uniform(20, 100)
dx = distance * math.cos(angle)
dy = distance * math.sin(angle)
color = random.choice(colors)
particle = self.canvas.create_oval(
x, y_target, x + 5, y_target + 5, fill=color, outline=color
)
particles.append((particle, dx, dy))
def animate_explosion():
for particle, dx, dy in particles:
self.canvas.move(particle, dx * 0.1, dy * 0.1)
pos = self.canvas.coords(particle)
if pos[0] < 0 or pos[1] < 0 or pos[2] > self.width or pos[3] > self.height:
self.canvas.delete(particle)
particles.remove((particle, dx, dy))
if particles:
self.root.after(50, animate_explosion)
animate_explosion()
def animate_rocket():
nonlocal y_start
if y_start > y_target:
self.canvas.move(rocket, 0, -10)
y_start -= 10
self.root.after(30, animate_rocket)
else:
explode()
animate_rocket()
def start_fireworks(self):
self.create_rocket()
self.root.after(1000, self.start_fireworks)
def run(self):
self.start_fireworks()
self.root.mainloop()
if __name__ == "__main__":
app = FireworksApp()
app.run()
Заключение
В ходе статьи мы с Вами написали код для анимации запуска фейерверков на Python. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂
Мой Telegram канал
Мой YouTube канал
Мой курс по Python (50 видоуроков + дополнительные уроки)
Курс по созданию телеграм-ботов на Python с фреймворком Aiogram