「The Nature of Code」から境界について取り上げます。境界を作るにはChainShapeクラスを利用します。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
境界(床面)を作る
3つの頂点を持つChainShapeを作ります。これが境界(床面)です。
以下は、境界の参考例です。
//ChainShape with three hard-coded vertices import shiffman.box2d.*; import org.jbox2d.collision.shapes.*; import org.jbox2d.common.*; import org.jbox2d.dynamics.*; Box2DProcessing box2d; ArrayList<Particle> particles; Surface surface; void setup(){ size(200, 200); box2d = new Box2DProcessing(this); box2d.createWorld(); //重力 box2d.setGravity(0, -10); particles = new ArrayList<Particle>(); surface = new Surface(); } void draw(){ background(255); box2d.step(); //particleの追加 if(random(1) < 0.2){ float sz = random(4, 8); particles.add(new Particle(width/2, 30, sz)); } //境界の表示 surface.display(); //particleの表示 for(Particle p : particles){ p.display(); } //ウィンドウから外れたparticlesをbox2dとリストから削除 for(int i = particles.size()-1; i >=0; i--){ Particle p = particles.get(i); if(p.done()){ particles.remove(i); } } }
class Particle{ Body body; float r; //コンストラクタ Particle(float x, float y, float r_){ r = r_; //box2dにパーティクルを設定 makeBody(x, y, r); } //box2dからパーティクルを削除 void killBody(){ box2d.destroyBody(body); } //パーティクルの生存判定 boolean done(){ //パーティクルの位置 Vec2 pos = box2d.getBodyPixelCoord(body); //ウィンドウから外れているときの処理 if(pos.y > height+r*2){ killBody(); return true; } return false; } //図形の描画 void display(){ Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); pushMatrix(); translate(pos.x, pos.y); rotate(-a); fill(175); stroke(0); strokeWeight(2); ellipse(0, 0, r*2, r*2); line(0, 0, r, 0); popMatrix(); } //box2dにパーティクルを設定 void makeBody(float x, float y, float r){ //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.DYNAMIC; bd.position.set(box2d.coordPixelsToWorld(x, y)); body = box2d.createBody(bd); //形状の定義 CircleShape cs = new CircleShape(); cs.m_radius = box2d.scalarPixelsToWorld(r); FixtureDef fd = new FixtureDef(); fd.shape = cs; fd.density = 1; fd.friction = 0.01; fd.restitution = 0.3; body.createFixture(fd); //速度の初期値をランダムとする body.setLinearVelocity(new Vec2(random(-10f, 10f), random(5f, 10f))); body.setAngularVelocity(random(-10, 10)); } }
class Surface{ ArrayList<Vec2> surface; //コンストラクタ Surface(){ surface = new ArrayList<Vec2>(); surface.add(new Vec2(0, height/2+50)); surface.add(new Vec2(width/2, height/2+50)); surface.add(new Vec2(width, height/2)); //配列の生成 Vec2[] vertices = new Vec2[surface.size()]; //配列にデータを代入する for(int i = 0; i < vertices.length; i++){ vertices[i] = box2d.coordPixelsToWorld(surface.get(i)); } ChainShape chain = new ChainShape(); chain.createChain(vertices, vertices.length); //ボディの定義 BodyDef bd = new BodyDef(); Body body = box2d.world.createBody(bd); body.createFixture(chain, 1); } //図形の描画 void display(){ strokeWeight(1); stroke(0); fill(0); beginShape(); for(Vec2 v: surface){ vertex(v.x, v.y); } vertex(width, height); vertex(0, height); endShape(CLOSE); } }
vertex
vertexとは、頂点のことです。
vertextの記述例は以下のとおりです。
size(200, 200); beginShape(); vertex(50, 50); vertex(50, 150); vertex(150, 150); vertex(150, 50); //endShape(); //終端を閉じない endShape(CLOSE); //終端を閉じる
まとめ
「The Nature of Code」から境界について取り上げました。境界を作るのにChainShapeクラスを利用しました。引き続き、「The Nature of Code」の内容を勉強します。
参考書籍
※Javaの勉強にもなるので一石二鳥です。