개발 꿀팁/PYTHON

[python] 설날 불꽃쇼

Jammie 2022. 11. 21. 15:29
반응형

1.로딩 라이브러리

본문의 불꽃쇼를 실현하려면 먼저 파이썬에 아래 라이브러리를 로드해야 합니다

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
#가져오기 라이브러리

2.배경사진과 음악 선택
  
다음으로 팝업창에서 배경 이미지와 음악을 선택합니다

if __name_ == '_main_':
root = tk.Tk( )
root.title('축하합니다-소년대길') # 폼의 제목 표시줄 설정
cv = tk.Canvas(root, height=600, width=600)
#높이 600, 폭 600 캔버스 그리기
bgpath = filedialog.askopenfilename (title='배경 그림을 선택하십시오')
#배경 이미지 선택
image = Image.open (bgpath)
#배경 이미지 열기
image = image.resize (600,600), Image.ANTIALIAS)
#배경사진을 창 크기로 조정
photo = ImageTk.PhotoImage (image)
cv.create_image(0, 0, image=photo, anchor='nw')
#캔버스에 배경 그림 그리기
bgmusic = filedialog.askopenfilename (title='배경음악을 선택하십시오')
py.mixer.init( )
# 초기화
py.mixer.music.load(bgmusic)
# 파일 로드
py.mixer.music.play(-1, 0, fade_ms=50)
# 재생 첫 번째는 재생 값 -1은 순환 재생을 의미하고 두 번째 인자는 재생을 시작하는 시간을 나타냅니다
py.mixer.music.pause( )
#타임아웃
py.mixer.music.unpause( )
#일시정지 취소
cv.pack( )
#cv를 추가하다
root.protocol("WM_DELETE_WINDOW", close)
root.after(200, simulate, cv)
#0.1초 후 stimulate 함수를 호출하여 불꽃놀이 효과 생성
root.mainloop( )
#루트 실행, 창 생성

3.동적 효과 설정
  
동적 효과 설정 단계에서 불꽃놀이 과정을 시뮬레이션합니다.먼저 입자 확장 단계, 그 다음 체류 단계, 자유 낙하 단계, 그리고 마지막으로 소멸입니다.동시에 머무르는 단계에서 화면에 표현하고 싶은 문자를 그립니다(스스로 변경 가능)

def randomcolor():
#랜덤 컬러 생성
colArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
color = ""
for i in range(6):
color += colArr[random.randint(0,14)]
return "#" + color
​
그라비티 = 0.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 (astar) before falling and getting removed
프롬 캔버스
Attributes (속성):
- 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
#불꽃이 피다 x축
self.y = y
#불꽃이 y축을 터뜨리다
self.initial_speed = explosion_speed
#입자초기속도
self.vx = vx
#입자운동x축속도
self.vy = vy
#입자운동 y축속도
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, outline='white', width=0.01)
# 한정 사각형 지정 (Tkinter가 자동으로 이 직사각형 안에 타원을 그립니다)
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
#입자의 x축은 계속 팽창한다
move_y = sin(radians(self.id*360/self.total))*self.initial_speed
#입자의 y축은 계속 팽창한다
self.cv.move(self.cid, move_x, move_y)
#id에 따라 캔버스 위의 입자를 x와 y의 거리만큼 움직인다
self.vx = move_x/(float(dt)*1000)
#입자의 x축 속도

elif self.alive():
columnFont = ('중국어 행해', 14)
#만약 입자가 확장되지 않고 생존만 한다면(최대로 부풀어 올랐다는 의미) 자유낙하
self.cv.create_text(250, 100, text='새로운'', tag='write_tag', fill=choice(colors), font=columnFont) # 글꼴
self.cv.create_text(300, 100, text='년', tag='write_tag', fill=choice(colors), font=columnFont)
self.cv.create_text(350, 100, text="빠르다"), tag="write_tag", fill=choice(colors), font = columnFont)
self.cv.create_text(400, 100, text='락', tag='write_tag', fill=choice(colors), font=columnFont)
#텍스트 태그 삭제
move_x = cos(radians(self.id*360/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축 업데이트

elif self.cid is not None:
#만약 입자의 라이프사이클이 지났다면 제거
cv.delete(self.cid)
#캔버스에서 파티클 오브젝트 제거
self.cv.delete("write_tag")
# 동시에 글꼴 제거
self.cid = None

def expand (self):
#팽창 효과 시간 프레임 정의
return self.age <= 1.2
#팽창시간이 1.2초 미만인지 판단

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( )
#1970년 이후 경과한 부동소수점 초를 소수점 이하 7자리까지 정확하게 돌려준다
explode_points = []
#폭발 지점 목록, 불꽃놀이 목록
wait_time = randint(10,100)
#대기 시간은 10에서 100 사이의 정수
numb_explode = randint(8,20)
#폭발 불꽃 개수 시 6부터 10까지의 랜덤 정수
# create list of list of all particles in all simultaneous explosion
for point in range(numb_explode):
#모든 모의 불꽃이 터지는 모든 입자를 위한 목록 만들기
if point<=4:
objects = [ ]
#점별 폭발 입자 목록
x_cordi = 250 + point*50
#폭발 지점별 x축
y_cordi = 100
#폭발점마다 y축
speed = uniform (0.5, 1.5)
#폭발 지점별 속도
size = uniform (0.5,3)
#폭발 지점별 크기
color = choice(colors)
#폭발점별 색상
explosion_speed = uniform(0.6, 3)
#폭발 속력
total_particles = randint(10,60)
#불꽃의 총 입자 수
for i in range(1, total_particles):
#같은 불꽃이 터지면서 나오는 입자의 크기, 속도, 좌표는 모두 같다
r = part(cv, idx = i, total = total_particles, explosion_speed, x = x_cordi, y = y_cordi, vx = speed, vy = speed, color= color, size = size, lifespan = uniform(0.6,1.75))
#상기 매개변수를 part 함수에 대입하지만, 각 입자의 생존 시간은 스스로 독립한다.
objects.append(r)
#r을 입자 목록에 추가
explode_points.append(objects)
#불꽃놀이 목록에 입자 목록 추가
else:
objects = [ ]
#점별 폭발 입자 목록
x_cordi = randint(50,550)
#폭발 지점별 x축
y_cordi = randint(50, 150)
#폭발점마다 y축
speed = uniform (0.5, 1.5)
#폭발 지점별 속도
size = uniform (0.5,3)
#폭발 지점별 크기
color = choice(colors)
#폭발점별 색상
explosion_speed = uniform(0.3, 2)
#폭발 속력
total_particles = randint(10,50)
#불꽃의 총 입자 수
for i in range(1, total_particles):
#같은 불꽃이 터지면서 나오는 입자의 크기, 속도, 좌표는 모두 같다
r = part(cv, idx = i, total = total_particles, explosion_speed, x = x_cordi, y = y_cordi, vx = speed, vy = speed, color= color, size = size, lifespan = uniform(0.6,1.75))
#상기 매개변수를 part 함수에 대입하지만, 각 입자의 생존 시간은 스스로 독립한다
objects.append(r)
#r을 입자 목록에 추가
explode_points.append(objects)
#불꽃놀이 목록에 입자 목록 추가
​

total_time = 0.0
#총 초기화 시간
# keeps undate within a timeframe of 1.8 second
while total_time < 2:
#총 시간이 1.8초보다 작을 때 사이클 실행
sleep(0.03)
#화면을 0.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( )

 

반응형