球の衝突運動について

 投稿者:lark12_long  投稿日:2014年 7月10日(木)17時38分23秒
  球の衝突をシミュレートしようと思い、プログラミングしたのですが、
壁との衝突反射については、正常に動く様ですが、
球と球の衝突動作が、奇妙な動きをして、どうにもギブアップ状態です

どなたか、模範プログラム提供願えればと思います

lark12_long

'
'    反射.bas
'
'     各球の質量は1、接触摩擦はなし
'
'     H26-07-10
'
'

width=1260
height=640
SET BITMAP SIZE width, height

reft=0
right=width
bottom=0
top=height

'左端,右端,下端,上端
  set window  left,right,bottom,top

'描画エリアの背景色着色範囲設定
set area color 1 !'黒
plot area : left,bottom;left,top;right,top;right,bottom
'--------------------------------------------------------------
xbase=100       '画面表示x起点
ybase=100       '画面表示y起点

randomize

n=8                   '球の数
dim x(n),y(n)         '球のx、y座標
dim vx(n),vy(n)       '球のx、y成分速度

wb=400                '枠の幅
hb=400                '枠の高さ

r=30                  '球の半径
dt=0.2                'サンプリングタイム

'初期位置設定
for i=0 to n-1
   xi=rnd*wb*10
   yi=rnd*hb*10
   if xi>0+r and xi<wb-r and yi>0+r and yi<hb-r then
     x(i)=xi
     y(i)=yi
   else
     i=i-1
   end if
next i

'初期速度設定
  for i=0 to n-1
    vx(i)=(rnd-0.5)*20*2
    vy(i)=(rnd-0.5)*20*2
  next i

do
    '位置の更新
    for i=0 to n-1
      x(i)=x(i)+vx(i)*dt
      y(i)=y(i)+vy(i)*dt

      '枠との衝突処理
      if x(i)<0+r then        '左の枠に衝突
        vx(i)=-vx(i)
        x(i)=r
      end if
      if x(i)>wb-r then
        vx(i)=-vx(i)           '右の枠に衝突
        x(i)=wb-r
      end if
      if y(i)<0+r then         '下の枠に衝突
        vy(i)=-vy(i)
        y(i)=r
      end if
      if y(i)>hb-r then         '上の枠に衝突
        vy(i)=-vy(i)
        y(i)=hb-r
      end if

      '球同士の衝突
       call cal1        'これが、上手くいきませんです
    next i

    '球の表示
    set draw mode hidden
    line(0,0)-(width,height),1,bf

    for i=0 to n-1
      col=mod(i,6)+2
      circle(xbase+x(i),ybase+y(i)),r,col,,,,f
    next i

   '枠の表示
   set line width 4
   line(xbase,ybase)-(xbase+wb,ybase+hb),6,b
   set draw mode explicit


loop
'-----------------------------------------------------
sub cal1
'球同士の衝突

  if n>=2 then
     for j=0 to n-1
       if i<>j then
          l=sqr( (x(i)-x(j))^2+(y(i)-y(j))^2 )  '球ij間距離
          v=sqr( vx(i)^2+vy(i)^2 )              '球iの衝突前の速度
          if l<=2*r and  v>0 and l>0 then       '衝突判定と、v=0、l=0の回避
            cosa=(x(i)-x(j))/l                  '球ij衝突時の球ijの中心線とx軸の成す角度aのcos値
            sina=(y(i)-y(j))/l                  '球ij衝突時の球ijの中心線とx軸の成す角度aのsin値
            cosc=vx(i)/v                        '球iの衝突時の球i速度ベクトルがx軸の成す角度cのcos値
            sinc=vy(i)/v                        '球iの衝突時の球i速度ベクトルがx軸の成す角度cのcos値
            cosd=cosa*sinc+cosc*sina            '衝突時の球ijの接触点法線と球iの速度ベクトルと成す角度dのcos値
            cosac=cosa*cosc-sina*sinc           '角度a+cのcos値
            cosdc=cosc*cosd-sinc*sind           '角度d+cのcos値
            sindc=cosc*sind+cosd*sinc           '角度d+cのsin値

            va=v*cosd                           '衝突後の球iの速度ベクトル
            vb=v*cosac                          '衝突後の球jの速度ベクトル

            vx(i)=va*cosdc                      '衝突後の球iのx成分速度
            vy(i)=va*sindc                      '衝突後の球iのy成分速度

            vx(j)=vb*cosa                       '衝突後の球jのx成分速度
            vy(j)=vb*sina                       '衝突後の球jのy成分速度

          end if
        end if
      next j
  end if
end sub
'-----------------------------------------------------


 

Re: 球の衝突運動について

 投稿者:SECOND  投稿日:2014年 7月11日(金)04時45分9秒
  lark12_longさんへのお返事です。

!動くように補修しただけで、ごめんください。

!十進BASICの書式になっています。
!--------------------------------------------------------------
!lark12_long
!
!    反射.bas
!
!     各球の質量は1、接触摩擦はなし
!
!     H26-07-10
!
!
LET width=641  !1260
LET HEIGHT=641 !640
SET BITMAP SIZE width, HEIGHT
!
LET left=0
LET right=width
LET bottom=0
LET top=HEIGHT
!
!左端,右端,下端,上端
SET WINDOW  left,right, bottom,top
!
!描画エリアの背景色着色範囲設定
SET AREA COLOR 1   !黒
PLOT AREA : left,bottom; left,top; right,top; right,bottom
!--------------------------------------------------------------
LET xbase=100      !画面表示x起点
LET ybase=100      !画面表示y起点
!
RANDOMIZE
!
LET n=8                   !球の数
OPTION BASE 0
DIM x(n),y(n), en(6,6),xb(n),yb(n)    !球のx、y座標
DIM vx(n),vy(n)           !球のx、y成分速度
!
LET wb=400                !枠の幅
LET hb=400                !枠の高さ
!
LET r=30                  !球の半径
LET dt=0.2                !サンプリングタイム
!
!初期位置設定
LET i=0
DO
   LET u=INT(6*RND)
   LET v=INT(6*RND)
   IF en(u,v)=0 THEN
      LET x(i)=r*(1.15+2.2*u)
      LET y(i)=r*(1.15+2.2*v)
      LET en(u,v)=1
      LET i=i+1
   END IF
LOOP UNTIL n<=i
!
!初期速度設定
FOR i=0 TO n-1
   LET vx(i)=(RND-0.5)*20*2
   LET vy(i)=(RND-0.5)*20*2
NEXT i
!
!位置の更新
DO
   FOR i=0 TO n-1
      LET xb(i)=x(i)
      LET yb(i)=y(i)
      LET x(i)=x(i)+vx(i)*dt
      LET y(i)=y(i)+vy(i)*dt
      !
      !枠との衝突処理
      IF x(i)< 0+r THEN         !左の枠に衝突
         LET vx(i)=-vx(i)
         LET x(i)=r
      END IF
      IF x(i)> wb-r THEN
         LET vx(i)=-vx(i)       !右の枠に衝突
         LET x(i)=wb-r
      END IF
      IF y(i)< 0+r THEN         !下の枠に衝突
         LET vy(i)=-vy(i)
         LET y(i)=r
      END IF
      IF y(i)> hb-r THEN        !上の枠に衝突
         LET vy(i)=-vy(i)
         LET y(i)=hb-r
      END IF
      !
      !球同士の衝突
      CALL cal1
   NEXT i
   SET DRAW mode hidden
   !
   !画面消去
   !line(0,0)-(width,height),1,bf
   SET AREA COLOR 1
   PLOT AREA :0,0; width,0; width,HEIGHT; 0,HEIGHT
   !
   !球の表示
   FOR i=0 TO n-1
   !col=mod(i,6)+2
   !circle(xbase+x(i),ybase+y(i)),r,col,,,,f
      SET AREA COLOR MOD(i,6)+2
      DRAW disk WITH SCALE(r)*SHIFT(xbase+x(i),ybase+y(i))
   NEXT i
   !
   !枠の表示
   SET LINE width 4
   !line(xbase,ybase)-(xbase+wb,ybase+hb),6,b
   SET LINE COLOR 6
   PLOT LINES: xbase,ybase; xbase+wb,ybase; xbase+wb,ybase+hb; xbase,ybase+hb; xbase,ybase
   !
   SET DRAW mode explicit
   WAIT DELAY .01
   mouse poll mox,moy,mlb,mrb
LOOP UNTIL 0< mrb

!----------------------------------
! 球同士の衝突( 球表面の摩擦係数0)
!----------------------------------
SUB cal1
   IF n>=2 THEN
      FOR j=0 TO n-1
         IF i<>j THEN
            LET lb=SQR( (xb(i)-xb(j))^2+(yb(i)-yb(j))^2)   !過去の球(i)(j)間距離
            LET  l=SQR( ( x(i) -x(j))^2+( y(i) -y(j))^2)   !現在の球(i)(j)間距離
            IF l<=2*r AND l< lb THEN                       !距離と、その増減で、衝突判定
               LET vi=SQR( vx(i)^2+vy(i)^2 )          !球(i)の速度の絶対値
               LET vj=SQR( vx(j)^2+vy(j)^2 )          !球(j)の速度の絶対値
               LET cosnx=(x(j)-x(i))/l                !球(i)中心を始点とする接触点法線ベクトルの角度 nx のcos 値
               LET sinnx=(y(j)-y(i))/l                !球(i)中心を始点とする接触点法線ベクトルの角度 nx のsin 値
               !--
               LET cosix=vx(i)/vi                     !球(i)速度ベクトルの角度 ix の cos 値
               LET sinix=vy(i)/vi                     !球(i)速度ベクトルの角度 ix の sin 値
               LET cosjx=vx(j)/vj                     !球(j)速度ベクトルの角度 jx の cos 値
               LET sinjx=vy(j)/vj                     !球(j)速度ベクトルの角度 jx の sin 値
               LET cos_in=cosix*cosnx+sinix*sinnx     !cos(ix-nx)
               LET sin_in=sinix*cosnx-cosix*sinnx     !sin(ix-nx)
               LET cos_jn=cosjx*cosnx+sinjx*sinnx     !cos(jx-nx)
               LET sin_jn=sinjx*cosnx-cosjx*sinnx     !sin(jx-nx)
               !--
               LET v_in=vi*cos_in                     !vi*cos(ix-nx) 接触点法線方向の、球(i)速度ベクトル
               LET v_jn=vj*cos_jn                     !vj*cos(jx-nx) 接触点法線方向の、球(j)速度ベクトル
               swap v_in, v_jn                        !接触点法線方向の、球(i)(j)速度ベクトル入替り
               LET v_it=vi*sin_in                     !vi*sin(ix-nx) 接触点接線方向の、球(i)速度ベクトル
               LET v_jt=vj*sin_jn                     !vj*sin(jx-nx) 接触点接線方向の、球(j)速度ベクトル
               !--
               LET vx(i)= v_in*cosnx -v_it*sinnx      !球(i)速度ベクトルの x 成分速度
               LET vy(i)= v_in*sinnx +v_it*cosnx      !球(i)速度ベクトルの y 成分速度
               LET vx(j)= v_jn*cosnx -v_jt*sinnx      !球(j)速度ベクトルの x 成分速度
               LET vy(j)= v_jn*sinnx +v_jt*cosnx      !球(j)速度ベクトルの y 成分速度
            END IF
         END IF
      NEXT j
   END IF
END SUB

END
 

Re: 球の衝突運動について

 投稿者:SECOND  投稿日:2014年 7月11日(金)13時20分46秒
  > No.3415[元記事へ]

以下のパーツが、少し楽になりました。もっと整理できるかもしれません。

!----------------------------------
! 球同士の衝突( 球表面の摩擦係数0)
!----------------------------------
SUB cal1
   IF n>=2 THEN
      FOR j=0 TO n-1
         IF i<>j THEN
            LET lb=SQR( (xb(i)-xb(j))^2+(yb(i)-yb(j))^2)   !過去の球(i)(j)間距離
            LET  l=SQR( ( x(i) -x(j))^2+( y(i) -y(j))^2)   !現在の球(i)(j)間距離
            IF l<=2*r AND l< lb THEN                       !距離と、その増減で、衝突判定
               LET nx=(x(j)-x(i))/l             !球(i)中心を始点とする接触点法線ベクトル x 成分
               LET ny=(y(j)-y(i))/l             !           〃  〃     y 成分
               !--
               LET v_in=nx*vx(i)+ny*vy(i)       !接触点法線方向の、球(i)速度ベクトル内積
               LET v_jn=nx*vx(j)+ny*vy(j)       !    〃    球(j)速度ベクトル内積
               swap v_in, v_jn                  !    〃    球(i)(j)速度ベクトル入替り
               LET v_it=-ny*vx(i)+nx*vy(i)      ! 〃 接線方向の、球(i)速度ベクトル内積
               LET v_jt=-ny*vx(j)+nx*vy(j)      !    〃    球(j)速度ベクトル内積
               !--
               LET vx(i)= nx*v_in -ny*v_it      !球(i)速度ベクトルの x 成分
               LET vy(i)= ny*v_in +nx*v_it      !     〃    y 成分
               LET vx(j)= nx*v_jn -ny*v_jt      !球(j)速度ベクトルの x 成分
               LET vy(j)= ny*v_jn +nx*v_jt      !     〃    y 成分
            END IF
         END IF
      NEXT j
   END IF
END SUB
 

戻る