Pythonで円花火を実装_完全なソースコード付き [第21回 - Python新年]

序文

花火は、お祝いやお祝い、祝い事などで美しく表現され、色とりどりの光とまばゆいばかりの形で人々に喜びと驚きをもたらします。このプロジェクトでは、Python プログラミング言語を使用して、画面上に円形の花火の効果を描画するシンプルで興味深いプログラムを作成します。

  • Python のグラフィック ライブラリ (pygame、turtle など) を使用して、画面上に円形の花火の効果を描画します。
  • 花火が画面上に生き生きと現れるダイナミックな演出を実現します。
  • 視覚的なインパクトを高めるために、花火が爆発した後の色の変化、軌跡のエフェクトなどの特殊効果を追加することを検討してください。

実装手順:

  • 必要なグラフィック ライブラリ (pygame など) をインポートします。
  • 画面を初期化し、ウィンドウサイズを設定します。
  • 花火の円形効果を描く関数を設計します。
  • メインプログラムでは、花火を描画する関数を呼び出し、画面上に花火のエフェクトを表示します。
  • 花火が上がったり、爆発したりするプロセスなど、花火のダイナミックな効果を追加することを検討してください。
  • プログラムを最適化し、特殊効果を追加して花火の美しさを向上させます。

レンダリング(動的)

ここに画像の説明を挿入します
ここに画像の説明を挿入します

完全なコード

# -*- coding: utf-8 -*-

import math, random,time
import threading
import tkinter as tk
import re
#import uuid

Fireworks=[]
maxFireworks=8
height,width=600,600

class firework(object):
    def __init__(self,color,speed,width,height):
        #uid=uuid.uuid1()
        self.radius=random.randint(2,4)  #粒子半径为2~4像素
        self.color=color   #粒子颜色
        self.speed=speed  #speed是1.5-3.5秒
        self.status=0   #在烟花未爆炸的情况下,status=0;爆炸后,status>=1;当status>100时,烟花的生命期终止
        self.nParticle=random.randint(20,30)  #粒子数量
        self.center=[random.randint(0,width-1),random.randint(0,height-1)]   #烟花随机中心坐标
        self.oneParticle=[]    #原始粒子坐标(100%状态时)
        self.rotTheta=random.uniform(0,2*math.pi)  #椭圆平面旋转角

        #椭圆参数方程:x=a*cos(theta),y=b*sin(theta)
        #ellipsePara=[a,b]

        self.ellipsePara=[random.randint(30,40),random.randint(20,30)]   
        theta=2*math.pi/self.nParticle
        for i in range(self.nParticle):
            t=random.uniform(-1.0/16,1.0/16)  #产生一个 [-1/16,1/16) 的随机数
            x,y=self.ellipsePara[0]*math.cos(theta*i+t), self.ellipsePara[1]*math.sin(theta*i+t)    #椭圆参数方程
            xx,yy=x*math.cos(self.rotTheta)-y*math.sin(self.rotTheta),  y*math.cos(self.rotTheta)+x*math.sin(self.rotTheta)     #平面旋转方程
            self.oneParticle.append([xx,yy])
        
        self.curParticle=self.oneParticle[0:]     #当前粒子坐标
        self.thread=threading.Thread(target=self.extend)   #建立线程对象
        

    def extend(self):         #粒子群状态变化函数线程
        for i in range(100):
            self.status+=1    #更新状态标识
            self.curParticle=[[one[0]*self.status/100, one[1]*self.status/100] for one in self.oneParticle]   #更新粒子群坐标
            time.sleep(self.speed/50)
    
    def explode(self):
        self.thread.setDaemon(True)    #把现程设为守护线程
        self.thread.start()          #启动线程
            

    def __repr__(self):
        return ('color:{color}\n'  
                'speed:{speed}\n'
                'number of particle: {np}\n'
                'center:[{cx} , {cy}]\n'
                'ellipse:a={ea} , b={eb}\n'
                'particle:\n{p}\n'
                ).format(color=self.color,speed=self.speed,np=self.nParticle,cx=self.center[0],cy=self.center[1],p=str(self.oneParticle),ea=self.ellipsePara[0],eb=self.ellipsePara[1])


def colorChange(fire):
    rgb=re.findall(r'(.{2})',fire.color[1:])
    cs=fire.status
    
    f=lambda x,c: hex(int(int(x,16)*(100-c)/30))[2:]    #当粒子寿命到70%时,颜色开始线性衰减
    if cs>70:
        ccr,ccg,ccb=f(rgb[0],cs),f(rgb[1],cs),f(rgb[2],cs)
    else:
        ccr,ccg,ccb=rgb[0],rgb[1],rgb[2]
        
    return '#{0:0>2}{1:0>2}{2:0>2}'.format(ccr,ccg,ccb)



def appendFirework(n=1):   #递归生成烟花对象
    if n>maxFireworks or len(Fireworks)>maxFireworks:
        pass
    elif n==1:
        cl='#{0:0>6}'.format(hex(int(random.randint(0,16777215)))[2:])   # 产生一个0~16777215(0xFFFFFF)的随机数,作为随机颜色
        a=firework(cl,random.uniform(1.5,3.5),width,height)
        Fireworks.append( {
    
    'particle':a,'points':[]} )   #建立粒子显示列表,‘particle’为一个烟花对象,‘points’为每一个粒子显示时的对象变量集
        a.explode()
    else:
        appendFirework()
        appendFirework(n-1)


def show(c):
    for p in Fireworks:                #每次刷新显示,先把已有的所以粒子全部删除
        for pp in p['points']:
            c.delete(pp)
    
    for p in Fireworks:                #根据每个烟花对象,计算其中每个粒子的显示对象
        oneP=p['particle']
        if oneP.status==100:        #状态标识为100,说明烟花寿命结束
            Fireworks.remove(p)     #移出当前烟花
            appendFirework()           #新增一个烟花
            continue
        else:
            li=[[int(cp[0]*2)+oneP.center[0],int(cp[1]*2)+oneP.center[1]] for cp in oneP.curParticle]       #把中心为原点的椭圆平移到随机圆心坐标上
            color=colorChange(oneP)   #根据烟花当前状态计算当前颜色
            for pp in li:
                p['points'].append(c.create_oval(pp[0]-oneP.radius,  pp[1]-oneP.radius,  pp[0]+oneP.radius,  pp[1]+oneP.radius,  fill=color))  #绘制烟花每个粒子

    root.after(50, show,c)  #回调,每50ms刷新一次

if __name__=='__main__':
    appendFirework(maxFireworks)
    
    root = tk.Tk()
    cv = tk.Canvas(root, height=height, width=width)
    cv.create_rectangle(0, 0, width, height, fill="black")

    cv.pack()

    root.after(50, show,cv)
    root.mainloop()
import pygame
import sys
import random

# 初始化pygame
pygame.init()

# 设置窗口大小
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Circle Fireworks")

# 定义烟花绘制函数
def draw_firework(x, y, color):
    pygame.draw.circle(screen, color, (x, y), 10)

# 主程序
def main():
    clock = pygame.time.Clock()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        # 清空屏幕
        screen.fill((0, 0, 0))

        # 生成随机位置和颜色的烟花
        firework_x = random.randint(50, screen_width - 50)
        firework_y = random.randint(50, screen_height - 50)
        firework_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

        # 绘制烟花
        draw_firework(firework_x, firework_y, firework_color)

        # 更新显示
        pygame.display.flip()

        # 控制帧率
        clock.tick(30)

if __name__ == "__main__":
    main()

コードの説明

このコードは、Python ライブラリを使用してグラフィカル インターフェイスを表示する、単純な花火アニメーション効果を実装しますtkinterコードの主な分析は次のとおりです。

  1. インポートモジュール:

    import math, random, time
    import threading
    import tkinter as tk
    import re
    

    数学的計算、乱数生成、スレッド、グラフィカル インターフェイス、正規表現などの必要なモジュールがインポートされます。

  2. グローバル変数の定義:

    Fireworks = []
    maxFireworks = 8
    height, width = 600, 600
    

    花火リスト、花火の最大数、キャンバスの高さと幅などのグローバル変数が定義されます。

  3. 花火のfirework定義:

    class firework(object):
        # ... (详细的初始化和方法定义在这里)
    

    Fireworks クラスは、Fireworks の初期化、状態変更スレッド ( extend)、爆発メソッド ( explode)、および__repr__オブジェクトの文字列表現のメソッドを含めて定義されています。

  4. 色変更機能colorChange

    def colorChange(fire):
        # ... (根据粒子状态计算颜色)
    

    色はパーティクルの状態に基づいて計算され、パーティクルの寿命が 70% に達すると、色は直線的に減衰し始めます。

  5. 花火発生機能appendFirework

    def appendFirework(n=1):
        # ... (递归生成烟花对象的函数)
    

    花火オブジェクトを再帰的に生成します。これには、花火の色、速度、初期座標などの情報の設定と、花火の爆発スレッドの開始が含まれます。

  6. 表示機能show:

    def show(c):
        # ... (每次刷新画布,绘制烟花粒子)
    

    キャンバスが更新されるたびに、花火のステータス、色、位置情報が更新されるなど、花火の粒子が描画されます。

  7. メインプログラムエントリ:

    if __name__=='__main__':
        # ... (初始化烟花,创建tkinter窗口并启动刷新循环)
    

    Fireworks を初期化し、tkinterウィンドウを作成し、更新ループを開始して、キャンバスを 50 ミリ秒ごとに更新します。

全体として、このコードはtkinter単純なウィンドウを作成し、そのウィンドウ内に複数の花火の効果を表示し、スレッドとタイマーを通じて花火のアニメーション効果を実装します。

要約する

このコードは、マルチスレッドとグラフィカル インターフェイス プログラミングの知識を組み合わせて、シンプルだが興味深い花火アニメーション効果を実装します。要約と感想は次のとおりです。

  1. マルチスレッドアプリケーション: Pythonのモジュールを利用することでthreading、花火の粒子の状態変化(メソッド)やアニメーション効果を実現しますextendこの方法により、プログラムは複数のタスクを同時に実行できるようになり、プログラムの応答性と同時実行性が向上します。

  2. グラフィカル インターフェイス プログラミング:tkinter簡単なウィンドウを作成し、キャンバスを介したアニメーション表示を実現するために使用しますCanvasこの方法により、プログラムはグラフィカル インターフェイスに花火の効果を表示できるようになり、ユーザーの視覚エクスペリエンスが向上します。

  3. 数学的および物理的モデル:花火の粒子座標は、数学における楕円パラメトリック方程式と平面回転方程式を使用して作成されました。この数学的モデルにより、花火の軌跡がより現実的で興味深いものになります。

  4. アニメーション効果の制御:パーティクルの状態と色を制御することで、花火のライフサイクルと色の変化の効果を実現します。このデザインにより、花火の演出がより鮮やかで多彩になります。

  5. 再帰の使用:花火オブジェクトは再帰的に生成され、複数の花火を同時に表示できます。オブジェクトを再帰的に生成するこの方法により、プログラム構造が明確になり、花火の管理と拡張が容易になります。

全体として、このプロジェクトは、グラフィカル インターフェイス プログラミングとマルチスレッドにおける Python の応用を実証するだけでなく、プログラミングにおける数学的および物理的モデルの使用を完全に反映しています。このプロジェクトを通じて、マルチスレッド プログラミング、グラフィカル インターフェイス設計、およびコンピュータ グラフィックスにおける数学的モデルの適用についてより深く理解することができます。

メッセージ

学習とプログラミングの旅では、常に自分自身に挑戦し、新しい領域を探索することが非常に重要です。コードのすべての行は学習の機会であり、すべてのバグは成長の機会であることを忘れないでください。好奇心を持ち、知識を渇望し、常に学ぶ姿勢を持ち続けてください。

たとえどんな困難や課題に直面しても、自分の能力を信じ、粘り強い努力がいつかは成功につながると信じてください。同時に、他の人と協力し、経験を共有し、一緒に進歩することは、チームにとって不可欠な部分です。

プログラミングは芸術であり、創造性はその魂です。勇気を持って作成して試し、コードを表現手段としてあなたの考えや情熱を伝えてください。最も重要なのは、プログラミングのプロセスを楽しみ、問題を解決することを楽しむことです。

あなたのコードが世界を変え、あなたの探求の道がますます広くなり、あなたのプロジェクトが創造性と成果に満ち溢れますように。さあ、未来は明るいです!
ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/weixin_52908342/article/details/135424881