プログラミング言語「Python」で制作 Part116 | Photoshop CC Tutorials

今回はプログラミング言語の「Python」を使って作成しました。

 

下記の本のサンプル「多重振り子のシミュレーション」をPygameで動くように移植しました。

 

■ プログラム

import traceback

try:
    import sys
    import math
    import random
    import pygame
    from pygame.locals import QUIT, KEYDOWN, K_LEFT, K_RIGHT, K_SPACE, Rect

    def array(N1, N2=0, N3=0):
        if N2 == 0 and N3==0: return [0 for i in range(N1)]
        elif N3 == 0: return [[0 for i in range(N2)] for j in range(N1)]
        else: return [[[0 for i in range(N3)] for j in range(N2)]
                      for k in range(N1)]

    #--------------------------------------------------------------
    # シミュレーション
    #--------------------------------------------------------------
    def Sim():
        global t, dt, g, KFact,PaM, F, ID1, ID2, KFact, aTH, adTH

        mG0 = 0; DMg = PaM * g
        for i in range(Num):
            mG0 += DMg; F[i]= -mG0 * math.sin(aTH[i][ID1])
            adTH[i][ID2]= adTH[i][ID1]+ F[i]*dt; mG0 *=KFact
        TH = 0
        for i in range(Num-1, -1, -1):
            TH += adTH[i][ID1]
            adTH[i][ID2]= adTH[i][ID2]* (1 - Myu)
            aTH[i][ID2]= aTH[i][ID1]+ adTH[i][ID2]*dt
    
    #--------------------------------------------------------------
    # おもり位置の変更
    #--------------------------------------------------------------
    def draw(SURFACE, ID1):#
        global XStart, YStart, SC, aX, bX, aY, bY,PaL
        global LID,BID

        X1 = XStart; Y1 = YStart
        for i in range(Num-1,-1, -1):
            cosTH = math.cos(aTH[i][ID1]); sinTH = math.sin(aTH[i][ID1])
            X2 = PaL * sinTH + X1;   Y2 = PaL * cosTH + Y1
            pygame.draw.line(SURFACE, (0, 255, 0), (X1, Y1), (X2, Y2))
            pygame.draw.ellipse(SURFACE, (255, 0, 0), (X2-10/2, Y2-10/2, 10, 10))

            X1 = X2; Y1 = Y2
    #--------------------------------------------------------------
    # メイン処理
    #--------------------------------------------------------------
    # Pygame初期設定
    pygame.init()
    SURFACE = pygame.display.set_mode((400, 500))
    FPSCLOCK = pygame.time.Clock()
    fps = 60

    #パラメータ設定
    PI  = math.pi; SC = 2000; XStart = 200; YStart = 10
    PaL =16             # 棒の長さ
    PaM =0.1           # おもりの重さ
    Num=30             # 分割数
    TH=30*PI/180       # 初期角度
    g   =9.8           # 重力加速度
    dt  =0.05          # 時間刻み
    Myu =0.001         # 粘性抵抗(人工拡散項を考慮する)
    KFact=1            #伝達係数
    LOOP=2000           # シミュレーション回数
    #初期設定(接頭文字a, bがおもりを示す)     
    a=array(Num,2);F=array(Num);LID=array(Num); BID=array(Num)
    aTH=array(Num,2); adTH=array(Num,2)  # θ, Δθ
    for i in range(Num):
        aTH[i][0]=TH; adTH[i][0]=0
    t=0; ID1=0;ID2=1
    #初期描画
    X1 = XStart; Y1 = YStart
    pygame.draw.ellipse(SURFACE, (255, 255, 0), (X1-2/2, Y1-2/2, 2, 2))

    for i in range(Num-1,-1, -1):
        cosTH = math.cos(aTH[i][ID1]); sinTH = math.sin(aTH[i][ID1])
        X2 = PaL * sinTH + X1;   Y2 = PaL * cosTH + Y1

        pygame.draw.line(SURFACE, (0, 0, 255), (X1, Y1), (X2, Y2))
        pygame.draw.ellipse(SURFACE, (255, 255, 0), (X2-2/2, Y2-2/2, 2, 2))

        X1 = X2; Y1 = Y2

    #--------------------------------------------------------------
    # ループ処理
    #--------------------------------------------------------------
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        #シミュレーション開始
        Sim()
        #-----------------------------------------------------------
        # 描画処理
        #-----------------------------------------------------------
        SURFACE.fill((0, 0, 0))
        draw(SURFACE, ID1)
        ID = ID1
        ID1 = ID2
        ID2 = ID

        pygame.display.update()
        FPSCLOCK.tick(fps)

except Exception as e:
    print("エラー情報\n" + traceback.format_exc())

input()

 

■ 参考書

「Python 3.6 による 力学シミュレーション 第7巻: 複合運動」

 

■ ゲーム用ライブラリ

「Pygame」

 

■ プログラミング言語

「Python」