상세 컨텐츠

본문 제목

2차원(평면) 충돌의 액션 구현 -완성-

프로그래밍 관련/물리,충돌,계산

by AlrepondTech 2011. 11. 23. 13:26

본문

반응형

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 



출처: http://cafe.naver.com/flashdev.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1530&



1. 학습목표

    평면 상에서의 운동량 보존의 법칙을 액션으로 구현할 수 있다.

 

지난 강좌에서 배운 내용 복습하기(사전 지식)

 
운동량 보존 법칙 :
 
반발 계수 :

 

2. 운동량 보존 법칙의 액션 구현

 

1. 공 그림의 무비클립을 만들어 식별자를 써 넣는다. (여기선 ball이라고 합시다.)

2. 첫번째 프레임에 다음과 같이 써서 무비클립을 삽입하고 왼쪽과 오른쪽에 각각 위치 시킨다.

   그리고 질량 값을 랜덤하게 갖도록 하여 크기를 결정하고 초기의 x축 방향 속도와 y축 방향의

   속도를 랜덤하게 준다. 아울러 사방의 벽에서 튕겨 내도록 한다. (누군가 색이 혼동된다기에...)

 

ma=10+random(20);  

mb=10+random(20);

vax=2+random(10);

vay=2+random(10);

vbx=2+random(10);

vby=2+random(10);

_root.attachMovie("ball","ballA",1); 

_root["ballA"]._x = 100;              
_root["ballA"]._y = 100;

_root["ballA"]._width=_root["ballA"]._height=10*Math.pow(ma, 1/3); 

_root.attachMovie("ball","ballB",2); 

_root["ballB"]._x = 400;              
_root["ballB"]._y = 100;

_root["ballB"]._width=_root["ballB"]._height=10*Math.pow(mb, 1/3);

clr=new Color(ballB);   //ballB라는 무비클립에 칼라를 새로 만듭니다.
clr.setRGB(0x0000FF); 
//칼라를 파란색으로 만듭니다.

this.onEnterFrame = function() {
  if (ballA._x-ballA._width/2+vax<10 || ballA._x+ballA._width/2+vax>490){
    vax *= -1;
  }

  if (ballA._y-ballA._width/2+vay<10 || ballA._y+ballA._width/2+vay>190){
    vay *= -1;
  }

  if (ballB._x-ballB._width/2+vbx<10 || ballB._x+ballB._width/2+vbx>490){
    vbx *= -1;
  }
  if (ballB._y-ballB._width/2+vby<10 || ballB._y+ballB._width/2+vby>190){
    vby *= -1;
  }

  ballA._x += vax;  
  ballA._y += vay;  
  ballB._x += vbx;  
  ballB._y += vby;  
};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

사전 계산 :  충돌 후 공 A와 B의 속도는 어떻게 될까?

 
# 전 시간에 배운 1차원 충돌에서의 충돌 후 A의 속력은 다음과 같습니다.
 
  
 
한편, 충돌 후 B의 속력은 다음과 같습니다.
 
 
 
 













 

 


자, 이제 평면상의 충돌을 생각해 봅시다. 우선 오른쪽 그림과 같이 평면상을 vb로 운동하던 B의 물체에 va로 운동하는 A가 점선(A의 중심과 B의 중심을 이은 점선)상에서 충돌하였습니다.
 
이 운동을 보다 세밀하게 살펴보기 위해 공 A와 B의 속력을 각각 분해하여 vax, vay와 vbx, vby로 나눌 수 있습니다. (전문 용어로 벡터의 분해 라고 부르는 고등학교 물리2 내용입니다. 잘 모르겠으면 다음의 주소에서 공부해보세요... ^^ http://mulinara.net/physics/mechanic/motion/k12.html
 
이 때 수평방향과 두 공의 중심을 이은 점선이 이루는 각이 θ라고 합시다. 이를 그림으로 나타낸 것이 다음과 같습니다.
 

 

 




공 A와 B가 충돌하는 선상을 새로운 x축(x'축)으로 놓고 vax와 vay의 x'성분을 합해줍니다. 그러니까 x'선상의 속도에 의한 또다른 1차원 충돌로 생각하자는 거죠. 따라서 공 A의 x'선상의 속도는 vax*cosθ+vay*sinθ가 되는 거죠. 같은 방법에 의해 공 B의 x'선상의 속도는 vbx*cosθ+vby*sinθ가 됩니다. 이 둘이 15강에서 배웠던 충돌 전의 속도(vA, vB)라고 생각하면 됩니다.
 
충돌 후 A의 x'선상의 속도를 vaxp(브이 엑스 프라임)이라고 한다면  식에 의해
 
vaxp = (ma-e*mb)/(ma+mb)*(vax*cosθ+vay*sinθ) +
         (mb+e*mb)/(ma+mb)*(vbx*cosθ+vby*sinθ)
 
가 됩니다. 같은 방법에 충돌 후 B의  x'선상의 속도를 vbxp이라고 한다면  식에 의해
 
vbxp = (ma+e*ma)/(ma+mb)*(vax*cosθ+vay*sinθ) +
         (mb-e*ma)/(ma+mb)*(vbx*cosθ+vby*sinθ)
 
가 됩니다. 이상은 x'축선상에서의 운동량 보존과 반발 계수를 적용한 것이라 볼 수 있습니다.
 

 

 




한 편 y'축 선상의 속도도 있을 것입니다. 당연히 y'축에 대해서도 운동량은 보존됩니다. 다만 충돌할 때 받는 힘은 두 공의 중심간의 상호작용이므로 공 A가 받는 힘과 공 B가 받는 힘(작용 반작용의 관계가 있는 힘)은 x'선상에 있게 됩니다.
 
충돌 전후에 속도가 변하는 것이 바로 이 힘때문인데 이 힘이 x'선상에서만 유효하므로 y'에 대한 운동에는 아무런 영향을 주지 못합니다. 마치 수직 아래로 작용하는 중력은 수평방향으로의 운동에 아무런 영향을 주지 못하는 것처럼요...
 
(포물선 운동에도 비슷한 원리를 적용할 수 있습니다. 중력이 수직 아래로 작용하기 때문에 수평방향으로는 속도의 변화를 일으킬 수 없어 수평 방향으로 등속운동을 한다고요... ^^)
 

 

 






 
결국 y'방향의 속도에는 아무런 변화가 없으므로 vayp는 vayp = vay*cosθ - vax*sinθ 가 되고 vbyp은 vbyp = vby*cosθ - vbx*sinθ 가 되는 것입니다.
 
마지막으로 고려해야할 내용이 있습니다. 운동량 보존법칙에 의해 구해진 vaxp, vayp, vbxp, vbyp는 x'과 y'선상의 속도라는 점입니다. 이를 다시 x축과 y축으로 환산 해 주어야 합니다.
 

 

 




따라서 충돌 후 x축 방향의 속도를 vax라 하면
 
vax = vaxp*cosθ- vayp*sinθ
 
가 되고 y축 방향의 속도를 vay라 하면
 
vay = vaxp*sinθ+vayp*cosθ
 
가 됩니다. 같은 방법으로 충돌 후 B의 속도는 x축과 y축 각각 다음과 같습니다.
 
vbx = vbxp*cosθ- vbyp*sinθ , vby = vbxp*sinθ+vbyp*cosθ

 

자 이제 식도 완성되었고 하니 액션으로 구현해 봅시다.

 

e=1;

ma=10+random(20);  

mb=10+random(20);

vax=2+random(10);

vay=2+random(10);

vbx=2+random(10);

vby=2+random(10);

_root.attachMovie("ball","ballA",1); 

_root["ballA"]._x = 100;              
_root["ballA"]._y = 100;

_root["ballA"]._width=_root["ballA"]._height=10*Math.pow(ma, 1/3); 

_root.attachMovie("ball","ballB",2); 

_root["ballB"]._x = 400;              
_root["ballB"]._y = 100;

_root["ballB"]._width=_root["ballB"]._height=10*Math.pow(mb, 1/3);

clr=new Color(ballB);  

clr.setRGB(0x0000FF); 

this.onEnterFrame = function() {

  if (ballA.hitTest(ballB)) {

     a = ballA._x-ballB._x;      //두 공사이의 x좌표 거리
    b = ballA._y-ballB._y;     //두 공사이의 y좌표 거리
    c = Math.sqrt(a*a+b*b);  //두 공사이의 직선 거리
    costheta = a/c;             //cosθ


    sintheta = b/c;                 

//sinθ

 

   

 

 

//다음은 앞에서 미리 계산한 식 그대로 쓴 거예요... ^^

    vaxp = (ma-e*mb)/(ma+mb)*(vax*costheta+vay*sintheta) +              (mb+e*mb)/(ma+mb)*(vbx*costheta+vby*sintheta);

    vbxp = (ma+e*ma)/(ma+mb)*(vax*costheta+vay*sintheta) +

             (mb-e*ma)/(ma+mb)*(vbx*costheta+vby*sintheta);

    vayp = vay*costheta - vax*sintheta;

    vbyp = vby*costheta - vbx*sintheta;

 

    vax = vaxp*costheta - vayp*sintheta;

    vay = vaxp*sintheta + vayp*costheta;

    vbx = vbxp*costheta - vbyp*sintheta;

    vby = vbxp*sintheta + vbyp*costheta;

  }
  if (ballA._x-ballA._width/2+vax<10 || ballA._x+ballA._width/2+vax>490){
    vax *= -1;
  }

  if (ballA._y-ballA._width/2+vay<10 || ballA._y+ballA._width/2+vay>190){
    vay *= -1;
  }

  if (ballB._x-ballB._width/2+vbx<10 || ballB._x+ballB._width/2+vbx>490){
    vbx *= -1;
  }
  if (ballB._y-ballB._width/2+vby<10 || ballB._y+ballB._width/2+vby>190){
    vby *= -1;
  }

  ballA._x += vax;  
  ballA._y += vay;  
  ballB._x += vbx;  
  ballB._y += vby;  
};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. 과제

 

 

 

 

 

 

 

 

1. 입자가 많은 경우 서로간의 충돌 효과는 어떻게 구현할 수 있을까...(과학사랑님한테 알려 달라고 한번 해보세요... ^^)

2. 가끔 두 입자가 서로 엉켜서 돌아다니곤 합니다. 원인을 찾아 해결해 보세요... ^^

 

 

 

 

=================================

=================================

=================================

 

 

 

 

반응형


관련글 더보기

댓글 영역