少し進んだスケッチのトップに戻る    印刷する

物理シュミレーションライブラリFisica

現実世界で物理法則に従って物が落下したり衝突したりするように、Processing画面上に描かれた「物体」の動きをシュミレーションする機能を提供するのが物理エンジン、あるいは物理場シュミレーションと呼ばれるライブラリです。Processing用のライブラリにFiscaがあります。Box2Dという物理エンジンのJava版をProcessingのライブラリ化したものです。

Fisica

Fisicaライブラリは、次のようにインポートできます。

メニュー[スケッチ][ライブラリをインポート][ライブラリ-を追加]で、Fisicaを選択して、インストールします。インストールすると、サンプルのContribute Librariesの中にサンプルが入るので、サンプルを動かして、機能を実験することができます。詳しくは、 FisicaのAPIを参照。 物理場に置く「物体」(FBodyクラス)にはさまざまな値を設定するためのメソッドが用意されています。下はその一部です。

ボールが落ちるサンプル

Processingのスケッチで、Fisicaの物体を物理場において運動のシュミレーションを実行するには次のようにします。 リストA2_1は、赤いボールが、斜めの箱にあたって落下するだけのスケッチです。
ボールが落ちる
【リストA2-1】
import fisica.*;   //(1)ライブラリをインポート
FWorld world;      //(2) FWorldオブジェクト用変数の定義
FBox bbox;
FCircle ball;
void setup() {
  size(400, 400);
  Fisica.init(this);     //(3)物理場の初期化
  world = new FWorld();  //(4)場の生成
  world.setEdges();      //(4)画面の端に境界を置く
  world.remove(world.bottom);  //(4)下だけ境界を外す
  //(5)箱を置く
  bbox = new FBox(200, 10);  //下線
  bbox.setPosition(width/2, height/2);//箱の位置
  bbox.setRotation(PI/10);//箱の回転
  bbox.setFill(0);//箱の色
  bbox.setStatic(true);//箱は落ちない
  world.add(bbox);
  //(5)ボールを置く
  ball = new FCircle(20); //ボールの生成
  ball.setPosition(width/2-50, 0);  //ボールの位置
  ball.setVelocity(random(-100, 100), 200);  //ボールの速度
  ball.setRestitution(0.8);  //ボールの反発
  ball.setFillColor(color(200, 0, 0));  //ボールの色
  ball.setNoStroke();
  world.add(ball);
}
void draw() {
  background(255);
  world.step();  //(6)シュミレーション実行
  world.draw();  //(7)オブジェクトを描画
}

マウス操作で物体が増えるサンプル

リストA2-2はマウス押下でボールが増えるサンプルです。FCircleオブジェクトはマウスが押されるごとに生成され、その数は不定です。前もって個数がわからないので、FCircleオブジェクトのデータの列を扱うためにArrayListを使います。
ArrayList <FCircle> balls= new ArrayList <FCircle> ();
配列はあらかじめ個数が定まっているデータの列ですが、ArrayListは不定の個数のデータの列を扱うためのデータ構造です。FCircleオブジェクトが生成されるたびにArrayListに入れます。
FCircle ball = new FCircle(d); //ボールの生成
//ballに対して、速度や色などを設定した後
world.add(ball);  //物理場に置く
balls.add(ball);  //ArrayListに入れる
    
ボールが落下して画面から出ても、物理場にオブジェクトは残り続けます。それを避けるため、ボールが完全に画面から消えたらFCircleをリストから削除します。
for (int i=0; i <balls.size(); i++) {    //ArrayListの要素のy座標を順に調べる
  if (balls.get(i).getY() > height+d ) { //dはボールの直径
    world.remove(balls.get(i)); //get(i)はインデックスiの要素をArrayListから取出す
  }
}
    
動きに変化を与えるために、箱の角度が-20度から20度で0.1度ずつ変化するようにしています(この部分はFisicaとは無関係)。
ボールが落ちる
【リストA2-2】
import fisica.*;
FWorld world;
FBox bbox;
FCircle ball;
ArrayList <FCircle> balls= new ArrayList <FCircle> ();
float d = 20;  //ボールの直径
float maxSlope = 30; //箱の角度の最大値
float angle;
float slope = 0.1;

void setup() {
  size(400, 400);
  Fisica.init(this);  //物理場の初期化
  world = new FWorld();  //場の生成
  world.setEdges();      //画面の端に境界を置く
  world.remove(world.bottom);  //下だけ境界を外す

  bbox = new FBox(200, 10);  //線状の箱
  bbox.setPosition(width/2, height/2);//箱の位置
  bbox.setFill(0);//箱の色
  bbox.setStatic(true);//箱は落ちない
  world.add(bbox);
}
void draw() {
  background(255);
  angle = angle + slope;  //箱を傾ける
  if (angle > maxSlope || angle < -maxSlope) {
    slope = -1* slope;
  }
  bbox.setRotation(radians(angle));//箱の回転
  world.step();  //シュミレーション実行
  world.draw();

  for (int i=0; i<balls.size(); i++) {  //ボールが下に消えていたらArrayListから削除
    if (balls.get(i).getY() > height+ d ) {
      world.remove(balls.get(i));
    }
  }
}
void makeBall() {  //ボールを生成し、値を設定する関数
  FCircle ball = new FCircle(d); //ボールの生成
  ball.setPosition(width/2-50, 0);  //ボールの位置
  ball.setVelocity(random(-100, 100), 200);  //ボールの速度
  ball.setRestitution(0.8);  //ボールの反発
  ball.setFillColor(color(200, 0, 0));  //ボールの色
  ball.setNoStroke();
  world.add(ball);  //物理場に置く
  balls.add(ball);  //ArrayListに入れる
}
void mousePressed() {
  makeBall();
}

演習問題


【問題A2-1】1秒ごとにボールが生まれ、箱の中に溜まり、60秒経ったら箱の底が抜けて、すべて落下するスケッチを作ってみよう。ボールがすべて落下したら、箱の底を元に戻し、再度ボールが溜まっていくようにして、1分の砂時計として時間のリズムパターンを刻むスケッチとしよう。
秒時計
秒時計
秒時計

arigat アットマーク acm.org / copyright © info