今回はプログラミング言語の「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)]
PI=math.pi
V1=0; X1=50; L1= 50; H1=50; M1=1.0; Myu1=0.005 # 物体 1 データ
V2=0; X2=300; L2=100; H2=50; M2=1.5; Myu2=0.005 # 物体 2 データ
DT=0.01; DTH=PI*DT; Kfact=1 # 実行用パラメータ
Hist=array(400,2); IHist=0; iDsp=2 # 履歴表示用
# Pygame初期設定
pygame.init()
SURFACE = pygame.display.set_mode((480, 400))
FPSCLOCK = pygame.time.Clock()
fps = 60
#--------------------------------------------------------------
# 履歴表示
#--------------------------------------------------------------
def history(SURFACE):
global Hist,IHist, X1, X2
Hist[IHist][0]=X1-100; Hist[IHist][1]=X2-300;IHist+=1
if IHist>=400: IHist=0
GH=200; GH1=GH-30; GH2=GH+30
ip=IHist;GX1=Hist[ip][0]+GH; GX2=Hist[ip][1]+GH
pygame.draw.line(SURFACE, (0, 255, 0), (50,GH), (450, GH))
for i in range(399):
ip+=1
if ip>=400: ip=0
GN1=Hist[ip][0]+GH; GN2=Hist[ip][1]+GH
if ip % 100==0:
pygame.draw.line(SURFACE, (0, 255, 0), (i+50,GH1), (i+50, GH2))
pygame.draw.line(SURFACE, (255, 0, 0), (i+50,GX1), (i+51, GN1))
pygame.draw.line(SURFACE, (0, 0, 255), (i+50,GX2), (i+51, GN2))
GX1=GN1; GX2=GN2
#--------------------------------------------------------------
# 計算
#--------------------------------------------------------------
def calc(F):
global M1,M2, Myu1,Myu2,X1,V1,X2,V2,Kfact
FS=(X2-X1-200)*Kfact
Acc=(F+FS)/M1; V1=(V1+Acc*DT)*(1-Myu1); X1+=V1*DT
Acc=-FS/M1; V2=(V2+Acc*DT)*(1-Myu2); X2+=V2*DT
#--------------------------------------------------------------
# 物体初期表示
#--------------------------------------------------------------
def initDraw(SURFACE,X,L,H,C):
LL=L;
pygame.draw.rect(SURFACE, C, (X-LL,100, LL, 100-H))
#--------------------------------------------------------------
# バネを直線で描く
#--------------------------------------------------------------
def initLine(SURFACE,X1, X2,H,C):
HH=100-H/2;
pygame.draw.line(SURFACE, C, (X1,HH*2 - H/2), (X2, HH*2 - H/2))
#--------------------------------------------------------------
# 物体の表示(座標位置変更)
#--------------------------------------------------------------
def Draw(SURFACE, X, L, H, C):
LL=L
pygame.draw.rect(SURFACE, C, ((X-LL,100), (LL, 100-H)))
pygame.draw.rect(SURFACE, (0, 0, 0), ((X-LL,100), (LL, 100-H)), 3)
#--------------------------------------------------------------
# バネの表示(座標位置変更)
#--------------------------------------------------------------
def DrawLine(SURFACE,X1, X2, H, C):
HH=100-H/2
pygame.draw.line(SURFACE, C, (X1,HH*2 - H/2), (X2, HH*2 - H/2), 2)
LID = initLine(SURFACE, X1, X2, H1, (0, 0, 0))
ID1 = initDraw(SURFACE, X1, L1, H1, (255, 0, 0))
ID2 = initDraw(SURFACE, X2, L2, H2, (0, 0, 255))
TH=0;N=0
#--------------------------------------------------------------
# ループ処理
#--------------------------------------------------------------
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#-----------------------------------------------------------
# 描画処理
#-----------------------------------------------------------
SURFACE.fill((255, 255, 255))
calc(200*math.sin(TH)); TH+=DTH
DrawLine(SURFACE, X1, X2, H1, (0, 0, 0)) # ばね
Draw(SURFACE, X1, L1, H1, (255, 0, 0)) # 赤物体
Draw(SURFACE, X2, L2, H2, ( 0, 0, 255)) # 青物体
N+=10
if N % iDsp==0:
history(SURFACE)
pygame.display.update()
FPSCLOCK.tick(fps)
except Exception as e:
print("エラー情報\n" + traceback.format_exc())
input()
■ 参考書
「Python 3.6 による 力学シミュレーション 第7巻: 複合運動」
■ ゲーム用ライブラリ
「Pygame」
■ プログラミング言語
「Python」