中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python炫酷煙花表白的源代碼分享

發布時間:2020-04-26 11:38:32 來源:億速云 閱讀:3404 作者:栢白 欄目:編程語言

天天敲代碼的朋友,有沒有想過代碼也可以變得很酷炫又浪漫?今天就教大家用Python模擬出綻放的煙花,工作之余也可以隨時讓程序為自己放一場煙花秀。

python炫酷煙花表白的源代碼分享

python炫酷煙花表白源代碼

這個有趣的小項目并不復雜,只需一點可視化技巧,100余行Python代碼和程序庫Tkinter,最后我們就能達到下面這個效果:

python炫酷煙花表白的源代碼分享

學完本教程后,你也能做出這樣的煙花秀。

整體概念梳理

我們的整個理念比較簡單。

python炫酷煙花表白的源代碼分享

如上圖示,我們這里通過讓畫面上一個粒子分裂為X數量的粒子來模擬爆炸效果。粒子會發生“膨脹”,意思是它們會以恒速移動且相互之間的角度相等。這樣就能讓我們以一個向外膨脹的圓圈形式模擬出煙花綻放的畫面。經過一定時間后,粒子會進入“自由落體”階段,也就是由于重力因素它們開始墜落到地面,仿若綻放后熄滅的煙花。

(推薦學習:編程學習課程)

基本知識:用Python和Tkinter設計煙花

這里不再一股腦把數學知識全丟出來,我們邊寫代碼邊說理論。首先,確保你安裝和導入了Tkinter,它是Python的標準 GUI 庫,廣泛應用于各種各樣的項目和程序開發,在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用于圖像處理,以及導入其它一些包,比如time,random和math。它們能讓我們更容易的控制煙花粒子的運動軌跡。

Tkinter應用的基本設置如下:

root = tk.Tk()

為了能初始化Tkinter,我們必須創建一個Tk()根部件(root widget),它是一個窗口,帶有標題欄和由窗口管理器提供的其它裝飾物。該根部件必須在我們創建其它小部件之前就創建完畢,而且只能有一個根部件。

w = tk.Label(root, text="Hello Tkinter!")

這一行代碼包含了Label部件。該Label調用中的第一個參數就是父窗口的名字,即我們這里用的“根”。關鍵字參數“text”指明顯示的文字內容。你也可以調用其它小部件:Button,Canvas等等。

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秒為“墜落”狀態,0.2秒處于Tkinter將其完全移除前的邊緣狀態)。

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代碼放了一場煙花秀:

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炫酷煙花表白的源代碼分享的詳細內容,更多請關注億速云其它相關文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西乌珠穆沁旗| 天气| 泗阳县| 浦北县| 兴国县| 淳安县| 丰宁| 曲阜市| 肇州县| 凤冈县| 兴城市| 和静县| 永清县| 阿拉善盟| 个旧市| 亳州市| 乐昌市| 高陵县| 军事| 巴彦淖尔市| 余江县| 嘉鱼县| 潮安县| 镇巴县| 东兴市| 将乐县| 扎赉特旗| 满城县| 富平县| 电白县| 屏南县| 河津市| 阳西县| 泰来县| 江门市| 鄂托克前旗| 宜良县| 黑山县| 蒙山县| 黄平县| 芷江|