今回はプログラミング言語の「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」