プログラミング言語「Python」で制作 Part113 | 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

    #■初期設定
    NumX = 50; NumY = 50
    Z=[[0 for j in range(NumY + 1)] for i in range(NumX + 1)]
    ID=[[0 for j in range(NumY + 1)] for i in range(NumX + 1)]
    ZX=[[0 for j in range(NumY + 1)] for i in range(NumX + 1)]
    ZY=[[0 for j in range(NumY + 1)] for i in range(NumX + 1)]

    def initHidden():
        XY=[[0,0] for i in range(4)]
        XY[0][0]=200;XY[0][1]=200; XY[1][0]=200;XY[1][1]=210
        XY[2][0]=210;XY[2][1]=210; XY[3][0]=210;XY[3][1]=200
        A=math.pi/9; B=math.pi/6; DX=5
        cosA=DX*math.cos(A);cosB=DX*math.cos(B)
        sinA=DX*math.sin(A);sinB=DX*math.sin(B)
        for i in range(NumX+1):
            for j in range(NumY+1):
                ZX[i][j]=250+(i*cosA-j*cosB)
                ZY[i][j]=250-(i*sinA+j*sinB)
        for i in range(NumX):
            for j in range(NumY):
                XY2 = [(XY[0][0], XY[0][1]), (XY[1][0], XY[1][1]), (XY[2][0], XY[2][1]), (XY[3][0], XY[3][1])]
                pygame.draw.polygon(SURFACE, (0, 100, 255), XY2)
                pygame.draw.lines(SURFACE, (0, 0, 0), True, XY2)

    #■隠れ線処理
    def hiddenLine(): 
        global canvas, NumX, NumY
        XY=[0 for i in range(8)]
        for i in range(NumX):
            i2=NumX-i;i1=i2-1
            for j in range(NumY):
                j2=NumX-j; j1=j2-1
                XY[0]=ZX[i1][j1]; XY[1]=ZY[i1][j1]-Z[i1][j1]
                XY[2]=ZX[i1][j2]; XY[3]=ZY[i1][j2]-Z[i1][j2]
                XY[4]=ZX[i2][j2]; XY[5]=ZY[i2][j2]-Z[i2][j2]
                XY[6]=ZX[i2][j1]; XY[7]=ZY[i2][j1]-Z[i2][j1]
                XY2 = [(XY[0], XY[1]), (XY[2], XY[3]), (XY[4], XY[5]), (XY[6], XY[7])]
                pygame.draw.polygon(SURFACE, (0, 100, 255), XY2)
                pygame.draw.lines(SURFACE, (0, 0, 0), True, XY2)

    ZS=[[[0 for j in range(NumY+1)] for i in range(NumX+1)] for k in range(2)]
    V =[[[0 for j in range(NumY+1)] for i in range(NumX+1)] for k in range(2)]
    simTime = 0; ID1 = 0; ID2 = 1; Myu=0.02;counter=0
    FreeBoundary=False # 境界条件を自由端にするときTrueにする
    captMode= False #画面キャプチャするときTrueにする

    def setData():  #データを設定
        for j in range(NumX+1):
            for k in range(NumY+1):
                Z[j][k]=80.0*ZS[ID1][j][k]

    def initWave():
        global simTime, ID1, ID2, Myu,counter,XS,V
        simTime = 0; ID1 = 0; ID2 = 1; Myu=0.02;counter=0
        for i in range(NumX+1):
            for j in range(NumY+1):
                DX = i - NumX/2; DY = j - NumY/2
                R = math.sqrt(DX * DX + DY * DY)
                if    R < 0.1: A=1
                elif  R > 3  : A=0
                else         : A = math.sin(R) / R;
                ZS[0][ i][ j] = -A;  V[0][ i][ j] = 0;
                #print(i,j,ZS[0][ i][ j])

    def waveEquation(SaveN, Alfa, DX, DT):
        global NumX, NumY, ZS, ID1,ID2,simTime,Myu,counter

        Beta = Alfa * Alfa / (DX * DX);
        for k in range(SaveN):
            for i in range(1, NumX):
                for j in range(1, NumY):
                    ZS[ID2][i][j] = ZS[ID1][i][j] + DT * V[ID1][i][j]
            for i in range(1, NumX):
                for j in range(1, NumY):
                    Acc = Beta * (ZS[ID2][i][j + 1] - 2 * ZS[ID2][i][j] +
                                  ZS[ID2][i][j - 1] + ZS[ID2][i + 1][j] -
                                  2 * ZS[ID2][i][j] + ZS[ID2][i - 1][j])
                    V[ID2][i][j] = V[ID1][i][j] + DT *(Acc- Myu*V[ID1][i][j])
            if FreeBoundary:  #自由端境界条件
                for i in range(NumX+1):
                    V [ID2][i][0]    = V [ID2][i][1]
                    V [ID2][i][NumY] = V [ID2][i][NumY-1]
                    ZS[ID2][i][0]    = ZS[ID2][i][1]
                    ZS[ID2][i][NumY] = ZS[ID2][i][NumY-1]
                for i in range(NumY+1):
                    V [ID2][0][i]    = V [ID2][1][i]
                    V [ID2][NumX][i] = V [ID2][NumX-1][i]
                    ZS[ID2][0][i]    = ZS[ID2][1][i]
                    ZS[ID2][NumX][i] = ZS[ID2][NumX-1][i]
            else: #固定端境界条件
                for i in range(NumX+1):
                    V[ID2][i][0] =0; V[ID2][i][NumY]= 0
                    ZS[ID2][i][0]=0; ZS[ID2][i][NumY]=0
                for i in range(NumY+1):
                    V[ID2][0][i] =0; V[ID2][NumX][i]=0
                    ZS[ID2][0][i]=0; ZS[ID2][NumX][i] = 0
            simTime += DT; ID1 = ID2; ID2 = 1-ID2;counter+=1
        return 0

    def leftMouseDown(event):#ダウン
        waveEquation(50, 0.05, 0.05, 0.01)
        setData(); hiddenLine();

    #■メイン処理
    # Pygame初期設定
    pygame.init()
    SURFACE = pygame.display.set_mode((500, 300))
    FPSCLOCK = pygame.time.Clock()
    fps = 60

    initHidden()
    initWave()
    if captMode:
        waveEquation(50, 0.05, 0.05, 0.01)
        setData(); hiddenLine();
    else:
        while(1):
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()

            #-----------------------------------------------------------
            # 描画処理
            #-----------------------------------------------------------
            SURFACE.fill((0, 0, 0))
            waveEquation(50, 0.05, 0.05, 0.01)
            setData()
            hiddenLine()

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

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

input()

 

■ 参考書

「Python 3.6 による 力学シミュレーション 第2巻: 振動」

 

■ ゲーム用ライブラリ

「Pygame」

 

■ プログラミング言語

「Python」