#author("2019-06-19T14:21:06+09:00","default:qua","qua")
#author("2020-09-21T10:49:26+09:00","default:qua","qua")
#navi(Processing/3.ライブラリの利用)
* 3-3-2 Fisicaで扱う物体 [#ra197657]
Fisicaで扱う物体には、剛体(FBody)、弾性体(FBlob)、これらをつなぐジョイント(FJoint)が用意されている。
** 剛体 [#z7184435]
剛体には線分(FLine)、球(FCircle)、箱(FBox)、多角形(FPoly)がある。 
- (x1, y1)から(x2, y2)までの線分は、 
  FLine stick;
のように線分の型をもつ変数stickを用意し、 
  stick = new FLine(x1, y1, x2, y2); 
のように作成し 
  world.add( stick ); 
で追加する。 
 
- 中心(x,y)にある直径rの球 
  FCircle ball; 
  ball = new FCircle(r); 
  ball.setPosition(x,y); 
  world.add(ball); 
 
- 中心が(x,y)、2辺の長さがw, h、傾きがth度の箱。傾き0ならばsetRotationは省略できる。 
  FBox brick; 
  brick = new FBox(w, h) 
  brick.setPosition(x, y); 
  brick.setRotation( radians(th) ); 
  world.add(brick); 
 
- 多角形は 
  new FPoly() 
で作成し、vertex(x,y)で頂点を追加していく。例えば、 
  b = new FPoly(); 
  b.vertex(10,20); 
  b.vertex(40,20); 
  b.vertex(10,60); 
  b.vertex(10,20); 
  world.add(b); 
で三角形が作成される。 
 
- いくつかの部品からなる物体 FCompound を設定することもできる。例えば、次のコードは振り子のような形の部品を作る。 
  pend = new FCompound(); 
  ball = new FCircle(20); 
  ball.setPosition( 100, 100 ); 
  thread = new FLine( 100, 0, 100, 100 ); 
  pend.addBody( ball ); 
  pend.addBody( thread ); 

** 弾性体 [#e20cbd92]
- 弾性体は 
  new FBlob() 
で作成し、多角形と同様にvertex(x,y)で頂点を追加していく。球形も作れて
  b = new FBlob(); 
  b.setAsCircle(cx, cy, r);
で、中心(cx,cy)、半径rの球が得られる。
 
** 部品の設定 [#g6605309]
bodyはいずれかの物体を表す。 
-物理的な初期設定
|body.setVelocity( vx, vy );|速度を指定する。|
|body.setPosition( x, y );|重心の位置を指定する。|
|body.setDensity( d );|密度を指定する。(指定がなければ1)|
|body.setDamping( b );|抵抗力の係数(1/60秒で速度が(1-b)倍になる)を指定する。(指定がなければ0.5)|
|body.setFriction( f );|摩擦係数(動摩擦係数、静止摩擦係数で共通)を指定する。摩擦力は垂直抗力のf倍となる。(指定がなければ0.5)|
|body.setRestitution( e );|跳ね返り係数を指定する。(指定がなければ0.1)|
|body.setRotation( th );|傾きを指定する(単位はラジアン)|
|body.setAngularVelocity( th );|重心の周りの回転角速度を指定する。|
|body.setAngularDamping( b );|回転抵抗力の係数(1/60秒で角速度が(1-b)倍になる)を指定する。(指定がなければ0.5)|
|body.setStatic(trueまたはfalse);|trueにすると物体は静止して動かない。(指定がなければfalse)|
|body.setRotatable(trueまたはfalse);|trueにすると物体は回転できる。(指定がなければtrue)|
|body.setGrabbable(trueまたはfalse);|trueにすると物体をマウスで動かせる。(指定がなければtrue)|
-見た目の設定
|body.setFill(r,g,b);|塗りつぶす色を(r,g,b)にする。(指定がなければ白)|
|body.setNoFill();|塗りつぶさない。|
|body.setStroke(r,g,b);|枠線の色を(r,g,b)にする。(指定がなければ黒)|
|body.setNoStroke();|枠線を描かない。|
|body.setStrokeWeight(w);|枠線の幅をwにする。|
-力を加える
|body.addForce(fx, fy);|重心に力(fx,fy)を加える。|
|body.addForce(fx, fy, x, y);|位置(x,y)に力(fx,fy)を加える。|
|body.addImpulse(ix, iy);|重心に力積(ix,iy)を加える。|
|body.addImpulse(ix, iy, x, y);|位置(x,y)に力積(ix,iy)を加える。|
-物体の位置や速度などを得る
|body.getX();|x方向の位置|
|body.getY();|y方向の位置|
|body.getVelocityX();|x方向の速度位置|
|body.getVelocityY();|y方向の速度位置|
|body.getVelocityX();|x方向の速度|
|body.getVelocityY();|y方向の速度|
|body.getMass();|質量|
|body.isTouchingBody( other )|otherと接触しているか?|

次の例は床に置かれた2つの球をシミュレートする。左の球の上でマウスをクリックすると右向きの力積が加えられる。
 import fisica.*;
 
 FWorld world;
 FCircle ball1, ball2;
 
 void setup(){
   size(600,300);
   Fisica.init(this);
   world = new FWorld();
   world.setEdges();
   world.setEdgesFriction( 0 );
   ball1=new FCircle(40);
   ball1.setDamping( 0 );
   ball1.setDensity( 2 );
   ball1.setFriction( 0.1 );
   ball1.setRestitution( 1 );
   ball1.setPosition( 50, 274.5 );
   ball1.setGrabbable( false );
   ball1.setFill( 128, 255, 128 );
   world.add( ball1 );
 
   ball2=new FCircle(40);
   ball2.setDamping( 0 );
   ball2.setDensity( 4 );
   ball2.setFriction( 0.1 );
   ball2.setRestitution( 1 );
   ball2.setPosition( 200, 274.5 );
   ball2.setGrabbable( false );
   ball2.setFill( 255, 128, 128 );
   world.add( ball2 );
 }
 
 void mouseClicked(){
   if( dist( mouseX, mouseY, ball1.getX(), ball1.getY() )<20 ){
     ball1.addImpulse( ball1.getMass()*100, 0 );
   }
 }
 
 
 void draw(){
   background(0);
   world.step();
   world.draw();
 }


また、上のプログラムのdraw()の部分を次のように書き換えると、2つの球が接触すると右側の球の色がしばらく(0.5秒ほど)青くなる。
 int counter = 0;
 void draw(){
   background(0);
   world.step();
   if( ball1.isTouchingBody( ball2 ) ){
     counter = 30;
   }
   if( counter>0 ){
     ball1.setFill( 0, 0, 255 );
     counter --;
   } else {
     ball1.setFill( 255 );
   }  
   world.draw();
 }
ここで、counterという変数が青く表示する時間を保持している。
   if( ball1.isTouchingBody( ball2 ) ){
     counter = 30;
   }
の部分で2つの球が接触するとcounterを30にセットする。以降、counterは青く表示する時間をカウントダウンし、0になると白で表示するようにする。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS