「The Nature of Code」からマウスジョイントについて取り上げます。マウスジョイントを利用して物体を引っ張ってみます。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
マウスジョイント
以下は、マウスジョイントで物体を引っ張る参考例です。
//MouseJoint demonstration 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.*; Box2DProcessing box2d; ArrayList<Boundary> boundaries; Box box; Spring spring; void setup(){ size(640, 360); box2d = new Box2DProcessing(this); box2d.createWorld(); box = new Box(width/2, height/2); spring = new Spring(); //境界 boundaries = new ArrayList(); boundaries.add(new Boundary(width/2, height-5, width, 10, 0)); boundaries.add(new Boundary(width/2, 5, width, 10, 0)); boundaries.add(new Boundary(width-5, height/2, 10, height, 0)); boundaries.add(new Boundary(5, height/2, 10, height, 0)); } void draw(){ background(255); box2d.step(); spring.update(mouseX, mouseY); for(int i = 0; i < boundaries.size(); i++){ Boundary wall = boundaries.get(i); wall.display(); } box.display(); spring.display(); } //マウスを押したときの処理 void mousePressed(){ if(box.contains(mouseX, mouseY)){ spring.bind(mouseX, mouseY, box); } } //マウスを離したときの処理 void mouseReleased(){ spring.destroy(); }
class Boundary{ float x; float y; float w; float h; Body b; //コンストラクタ Boundary(float x_, float y_, float w_, float h_, float a){ x = x_; y = y_; w = w_; h = h_; //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.STATIC; bd.angle = a; bd.position.set(box2d.coordPixelsToWorld(x, y)); b = box2d.createBody(bd); //ポリゴンの定義 PolygonShape sd = new PolygonShape(); float box2dW = box2d.scalarPixelsToWorld(w/2); float box2dH = box2d.scalarPixelsToWorld(h/2); sd.setAsBox(box2dW, box2dH); b.createFixture(sd, 1); } //図形の描画 void display(){ noFill(); stroke(127); fill(127); strokeWeight(1); rectMode(CENTER); float a = b.getAngle(); pushMatrix(); translate(x, y); rotate(-a); rect(0, 0, w, h); popMatrix(); } }
class Box{ Body body; float w; float h; //コンストラクタ Box(float x_, float y_){ float x = x_; float y = y_; w = 24; h = 24; makeBody(new Vec2(x, y), w, h); } boolean contains(float x, float y){ Vec2 worldPoint = box2d.coordPixelsToWorld(x, y); Fixture f = body.getFixtureList(); boolean inside = f.testPoint(worldPoint); return inside; } //図形の描画 void display(){ Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); rectMode(PConstants.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_){ //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.DYNAMIC; bd.position.set(box2d.coordPixelsToWorld(new Vec2(center))); body = box2d.createBody(bd); //ポリゴンの定義 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; body.createFixture(fd); body.setLinearVelocity(new Vec2(random(-5, 5), random(2, 5))); body.setAngularVelocity(random(-5, 5)); } }
class Spring{ MouseJoint mouseJoint; //コンストラクタ Spring(){ mouseJoint = null; } void update(float x, float y){ if(mouseJoint != null){ Vec2 mouseWorld = box2d.coordPixelsToWorld(x, y); //ターゲットをマウスの位置に設定 mouseJoint.setTarget(mouseWorld); } } //図形の描画 void display(){ if(mouseJoint != null){ Vec2 v1 = new Vec2(0, 0); mouseJoint.getAnchorA(v1); Vec2 v2 = new Vec2(0, 0); mouseJoint.getAnchorB(v2); v1 = box2d.coordWorldToPixels(v1); v2 = box2d.coordWorldToPixels(v2); stroke(0); strokeWeight(1); line(v1.x, v1.y, v2.x, v2.y); } } //マウス座標とBoxオブジェクトを紐付ける void bind(float x, float y, Box box){ //マウスジョイントの定義 MouseJointDef md = new MouseJointDef(); md.bodyA = box2d.getGroundBody(); md.bodyB = box.body; Vec2 mp = box2d.coordPixelsToWorld(x, y); md.target.set(mp); md.maxForce = 1000.0 * box.body.m_mass; md.frequencyHz = 5.0; md.dampingRatio = 0.9; mouseJoint = (MouseJoint)box2d.world.createJoint(md); } //マウスジョイントを取り除く void destroy(){ if(mouseJoint != null){ box2d.world.destroyJoint(mouseJoint); mouseJoint = null; } } }
まとめ
「The Nature of Code」からマウスジョイントについて取り上げました。マウスジョイントを利用して物体を引っ張ってみました。引き続き、「The Nature of Code」の内容を勉強します。
参考書籍
※Javaの勉強にもなるので一石二鳥です。