> 백엔드 개발 > 파이썬 튜토리얼 > 파이썬 멋진 불꽃놀이 고백 소스 코드

파이썬 멋진 불꽃놀이 고백 소스 코드

angryTom
풀어 주다: 2020-02-25 14:10:11
원래의
50432명이 탐색했습니다.

매일 코드를 입력하는 친구들, 코드도 멋지고 로맨틱해질 수 있다는 생각을 해보셨나요? 오늘은 Python을 사용하여 불꽃놀이를 시뮬레이션하는 방법을 가르쳐 드리겠습니다. 퇴근 후 언제든지 프로그램에서 불꽃놀이를 시작하도록 할 수도 있습니다.

파이썬 멋진 불꽃놀이 고백 소스 코드

Python 멋진 불꽃놀이 고백 소스 코드

이 흥미로운 작은 프로젝트는 약간의 시각화 기술, 100줄 이상의 Python 코드 및 프로그램 라이브러리 Tkinter만 필요합니다. 다음 효과:

파이썬 멋진 불꽃놀이 고백 소스 코드

이 튜토리얼을 학습한 후에는 이러한 불꽃놀이 쇼를 만들 수도 있습니다.

전체 컨셉 검토

저희 전체 컨셉은 비교적 간단합니다.

파이썬 멋진 불꽃놀이 고백 소스 코드

위 그림과 같이 화면상의 입자를 X개의 입자로 분할하여 폭발 효과를 시뮬레이션합니다. 입자는 "팽창"합니다. 즉, 입자는 일정한 속도와 서로 동일한 각도로 움직입니다. 이를 통해 확장되는 원 형태의 불꽃놀이를 시뮬레이션할 수 있습니다. 일정 시간이 지나면 입자는 "자유 낙하" 단계에 들어가며, 불꽃이 피었다가 꺼지는 것처럼 중력으로 인해 땅에 떨어지기 시작합니다.

(추천 학습: 프로그래밍 학습 과정)

기본 지식: Python과 Tkinter로 불꽃놀이 디자인하기

여기서 우리는 더 이상 모든 수학적 지식을 한꺼번에 버리지 않고, 코드를 작성하면서 이론에 대해 이야기합니다. 먼저, Python의 표준 GUI 라이브러리이며 다양한 프로젝트 및 프로그램 개발에 널리 사용되는 Tkinter를 설치하고 가져와야 합니다. Python에서 Tkinter를 사용하면 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
로그인 후 복사

Tkinter 외에도 인터페이스에 아름다운 배경을 제공하기 위해 이미지 처리를 위한 PIL은 물론 시간, 무작위 및 수학과 같은 기타 패키지도 가져옵니다. 이를 통해 불꽃놀이 입자의 궤적을 더 쉽게 제어할 수 있습니다.

Tkinter 애플리케이션의 기본 설정은 다음과 같습니다:

root = tk.Tk()
로그인 후 복사

Tkinter를 초기화하려면 Tk() 루트 위젯을 생성해야 합니다. 이는 창 관리자가 제공하는 제목 표시줄과 기타 장식이 있는 창입니다. 이 루트 위젯은 다른 위젯을 생성하기 전에 생성되어야 하며 루트 위젯은 하나만 있을 수 있습니다.

w = tk.Label(root, text="Hello Tkinter!")
로그인 후 복사

이 코드 줄에는 Label 구성 요소가 포함되어 있습니다. Label 호출의 첫 번째 매개변수는 여기서 사용하는 "루트"인 상위 창의 이름입니다. 키워드 인수 "text"는 표시할 텍스트 내용을 지정합니다. 버튼, 캔버스 등 다른 위젯을 호출할 수도 있습니다.

w.pack()
root.mainloop()
로그인 후 복사

다음 두 줄의 코드가 중요합니다. 여기서 패키징 방법은 Tkinter에게 사용된 위젯에 맞게 창 크기를 조정하도록 지시하는 것입니다. 창은 Tkinter 이벤트 루프에 들어가고 root.mainloop()에 의해 호출될 때까지 나타나지 않습니다. 스크립트는 창을 닫을 때까지 이벤트 루프에 유지됩니다.

불꽃놀이를 코드로 변환

이제 불꽃놀이의 각 입자를 나타내는 개체를 디자인합니다. 각 입자에는 모양과 움직임을 제어하는 ​​몇 가지 중요한 속성(크기, 색상, 위치, 속도 등)이 있습니다.

'''
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
로그인 후 복사

원래 아이디어를 다시 생각해보면, 각 불꽃이 폭발하도록 보장해야 하는 모든 입자는 "확장", "낙하", "사라짐"이라는 3가지 단계를 거쳐야 한다는 것을 알게 될 것입니다. 따라서 아래와 같이 파티클 클래스에 모션 기능을 더 추가합니다.

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
로그인 후 복사

물론 이는 각 파티클이 피어나는 시간과 떨어지는 시간을 정의해야 한다는 의미이기도 합니다. 이 부분에서는 최상의 시각적 효과를 얻기 위해 더 많은 매개변수를 시도해야 합니다.

# 定义膨胀效果的时间帧
def expand (self):
    return self.age <= 1.2
# 检查粒子是否仍在生命周期内
def alive(self):
    return self.age <= self.lifespan
로그인 후 복사

Tkinter 시뮬레이션 사용

이제 입자의 움직임을 개념화했지만 불꽃에는 입자가 하나만 있을 수 없고 불꽃쇼에도 불꽃이 하나만 있을 수 없다는 것은 분명합니다. 다음 단계는 Python과 Tkinter가 제어할 수 있는 방식으로 입자를 하늘로 지속적으로 "발사"하도록 하는 것입니다.

이 시점에서는 하나의 입자를 작동하는 것에서 여러 불꽃놀이와 각 불꽃놀이의 여러 입자를 화면에 표시하는 것으로 업그레이드해야 합니다.

저희 솔루션은 다음과 같습니다. 목록을 만들고 각 하위 목록은 입자 목록을 포함하는 불꽃입니다. 각 목록의 예는 동일한 x, y 좌표, 크기, 색상 및 초기 속도를 갖습니다.

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)
로그인 후 복사

다음 단계는 입자 속성이 정기적으로 업데이트되도록 하는 것입니다. 여기서는 0.01초마다 상태를 업데이트하고 1.8초 후에 업데이트를 중지하도록 입자를 설정했습니다. 즉, 각 입자는 1.6초 동안 존재하며, 그 중 1.2초는 "블룸" 상태이고 0.4초는 "하강" 상태입니다. Tkinter가 가장자리를 완전히 제거하기 전 가장자리에서 0.2초).

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__ == &#39;__main__&#39;:
    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 = [&#39;red&#39;, &#39;blue&#39;, &#39;yellow&#39;, &#39;white&#39;, &#39;green&#39;, &#39;orange&#39;, &#39;purple&#39;, &#39;seagreen&#39;, &#39;indigo&#39;, &#39;cornflowerblue&#39;]
&#39;&#39;&#39;
particles 类
粒子在空中随机生成随机,变成一个圈、下坠、消失
属性:
    - id: 粒子的id
    - x, y: 粒子的坐标
    - vx, vy: 在坐标的变化速度
    - total: 总数
    - age: 粒子存在的时长
    - color: 颜色
    - cv: 画布
    - lifespan: 最高存在时长
&#39;&#39;&#39;
class Particle:
    def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx=0., vy=0., size=2., color=&#39;red&#39;, 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&#39;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
&#39;&#39;&#39;
循环调用保持不停
&#39;&#39;&#39;
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__ == &#39;__main__&#39;:
    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=&#39;nw&#39;)
    cv.pack()
    root.protocol("WM_DELETE_WINDOW", close)
    root.after(100, simulate, cv)
    root.mainloop()
로그인 후 복사

众多python培训视频,尽在python学习网,欢迎在线学习!

위 내용은 파이썬 멋진 불꽃놀이 고백 소스 코드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿