今回はプログラミング言語の「Python」を使って作成しました。
下記の本のサンプル「振り子の衝突シミュレーション」をPygameで動くように移植しました。
■ プログラム
import traceback
try:
import time,math,winsound
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; PI3=PI/3
Myu = 0.0 # 粘性抵抗
e = 1 # 衝突係数
DT=0.05 # 時間刻み
M1=10; M2=10 # 振り子のおもりの重さ
R1=10; R2=10 # 振り子のおもり半径
L=100 # 振り子の棒の長さ
X0=120; Y0=10 # 振り子を吊るす位置の中心位置
X1=X0-R1; X2=X0+R2 # 振り子を吊るす位置のX座標
RID=array(2,2);TH=array(2);V=array(2)# 配列宣言
TH[1]=PI3 # 振り子 2 のおもりの初期位置
#--------------------------------------------------------------
# メイン処理
#--------------------------------------------------------------
# Pygame初期設定
pygame.init()
SURFACE = pygame.display.set_mode((240, 150))
FPSCLOCK = pygame.time.Clock()
fps = 60
#--------------------------------------------------------------
# 振り子位置移動
#--------------------------------------------------------------
def movePend(SURFACE, X0, Y0, L, R, TH, col):
X2=X0+L*math.sin(TH); Y2=Y0+L*math.cos(TH)
pygame.draw.line(SURFACE, (255, 255, 255), (X0, Y0), (X2, Y2))
pygame.draw.ellipse(SURFACE, col, (X2-R*2/2, Y2-R*2/2, R*2, R*2))
#--------------------------------------------------------------
# おもり衝突のチェック
#--------------------------------------------------------------
def checkCollision():
global X1,X2, Y0, R1, R2; RR=R1+R2;RR=RR*RR
XX1=X1+L*math.sin(TH[0]); YY1=Y0+L*math.cos(TH[0])
XX2=X2+L*math.sin(TH[1]); YY2=Y0+L*math.cos(TH[1])
DX=XX1-XX2; DY=YY2-YY1
if DX*DX+DY*DY<=RR: return True
return False
#--------------------------------------------------------------
# おもり衝突時の速度変更
#--------------------------------------------------------------
def Collision():
global e, M1, M2; MM=M1+M2; ee=1+e ; VV=V[0]
if abs(V[0]-V[1])>0.05: winsound.Beep(1026,50)
V[0]+= M2*ee*(V[1]-VV)/MM
V[1]-= M1*ee*(V[1]-VV)/MM
#--------------------------------------------------------------
# 衝突以外のおもりの移動の計算
#--------------------------------------------------------------
def calc():
global V,TH,DT,Myu
for i in range(2):
V[i]-=DT*(math.sin(TH[i])+V[i]*Myu)
TH[i]+=DT*V[i]
#--------------------------------------------------------------
# 振り子の描画
#--------------------------------------------------------------
def dsp(canvas):
global RID,X1,X2, Y0,L,R1,R2,TH
red = (255, 0, 0)
blue = (0, 0, 255)
movePend(SURFACE, X1,Y0, L,R1,TH[0], red)
movePend(SURFACE, X2,Y0, L,R2,TH[1], blue)
#--------------------------------------------------------------
# ループ処理
#--------------------------------------------------------------
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#-----------------------------------------------------------
# 描画処理
#-----------------------------------------------------------
SURFACE.fill((0, 0, 0))
calc()
dsp(SURFACE)
if checkCollision():
Collision()
pygame.display.update()
FPSCLOCK.tick(fps)
except Exception as e:
print("エラー情報\n" + traceback.format_exc())
input()
■ 参考書
「Python 3.6 による 力学シミュレーション 第7巻: 複合運動」
■ ゲーム用ライブラリ
「Pygame」
■ プログラミング言語
「Python」