「The Nature of Code」からオブジェクトを連結して橋を作ります。複数のパーティクルを連結して橋と見立てます。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
オブジェクトを連結して橋を作る
以下は、複数のパーティクルを連結して橋を作る参考例です。
//DistanceJoint import shiffman.box2d.*; import org.jbox2d.common.*; import org.jbox2d.dynamics.joints.*; import org.jbox2d.collision.shapes.*; import org.jbox2d.collision.shapes.Shape; import org.jbox2d.dynamics.*; import org.jbox2d.dynamics.contacts.*; Box2DProcessing box2d; Bridge bridge; ArrayList<Box> boxes; void setup(){ size(200, 200); box2d = new Box2DProcessing(this); box2d.createWorld(); bridge = new Bridge(width, width/2); boxes = new ArrayList<Box>(); } void draw(){ background(255); box2d.step(); //boxesの描画 if(random(1) < 0.2){ Box p = new Box(width/2, 30); boxes.add(p); } //boxesの描画 for(Box b: boxes){ b.display(); } for(int i = boxes.size()-1; i>=0; i--){ Box b = boxes.get(i); if(b.done()){ boxes.remove(i); } } //橋の描画 bridge.display(); }
class Bridge{ float totalLength; int numPoints; ArrayList<Particle> particles; //コンストラクタ Bridge(float l, int n){ totalLength = l; numPoints = n; particles = new ArrayList(); float len = totalLength / numPoints; for(int i = 0; i < numPoints+1; i++){ Particle p = null; if(i == 0 || i == numPoints){ //橋の両端 p = new Particle(i*len, height/4, 4, true); }else{ p = new Particle(i*len, height/4, 4, false); } particles.add(p); if(i > 0){ //連結処理 DistanceJointDef djd = new DistanceJointDef(); Particle previous = particles.get(i-1); djd.bodyA = previous.body; djd.bodyB = p.body; djd.length = box2d.scalarPixelsToWorld(len); djd.frequencyHz = 0; djd.dampingRatio = 0; DistanceJoint dj = (DistanceJoint)box2d.world.createJoint(djd); } } } //図形の描画 void display(){ for(Particle p: particles){ p.display(); } } }
class Particle{ Body body; float r; //コンストラクタ Particle(float x, float y, float r_, boolean fixed){ r = r_; //ボディの定義 BodyDef bd = new BodyDef(); if(fixed){ bd.type = BodyType.STATIC; }else{ bd.type = BodyType.DYNAMIC; } bd.position = box2d.coordPixelsToWorld(x, y); body = box2d.world.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.3; fd.restitution = 0.5; body.createFixture(fd); } 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(127); stroke(0); strokeWeight(2); ellipse(0, 0, r*2, r*2); line(0, 0, r, 0); popMatrix(); } }
class Box{ Body body; float w; float h; //コンストラクタ Box(float x, float y){ w = random(4, 16); h = random(4, 16); makeBody(new Vec2(x, y), w, h); } void killBody(){ box2d.destroyBody(body); } boolean done(){ Vec2 pos = box2d.getBodyPixelCoord(body); if(pos.y > height+w*h){ killBody(); return true; } return false; } //図形の描画 void display(){ Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); rectMode(CENTER); pushMatrix(); translate(pos.x, pos.y); rotate(-a); stroke(0); fill(127); strokeWeight(2); rect(0, 0, w, h); popMatrix(); } void makeBody(Vec2 center, float w_, float h_){ //ポリゴンの定義 PolygonShape sd = new PolygonShape(); float box2dW = box2d.scalarPixelsToWorld(w_/2); float box2dH = box2d.scalarPixelsToWorld(h_/2); sd.setAsBox(box2dW, box2dH); FixtureDef fd = new FixtureDef(); fd.shape = sd; fd.density = 1; fd.friction = 0.3; fd.restitution = 0.5; //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.DYNAMIC; bd.position.set(box2d.coordPixelsToWorld(center)); body = box2d.createBody(bd); body.createFixture(fd); body.setLinearVelocity(new Vec2(random(-5, 5), random(2, 5))); body.setAngularVelocity(random(-5, 5)); } }
まとめ
「The Nature of Code」からオブジェクトを連結して橋を作りました。引き続き、「The Nature of Code」の内容を勉強します。
参考書籍
※Javaの勉強にもなるので一石二鳥です。