「The Nature of Code」から衝突イベントとヒットしたオブジェクトの判別について取り上げます。物体が衝突したあとに、その物体がどのようなオブジェクトなのか判別します。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
衝突イベントとヒットしたオブジェクトの判別
物体が衝突したあとに物体がどのようなオブジェクトなのか判別します。オブジェクトの型の種類によって、処理の内容を変更します。以下は、その参考例です。
//CollisionsAndControl //独自のモーションでオブジェクトを制御する基本的な例 //どのオブジェクトがヒットしたか知る方法 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; Box box; ArrayList<Particle> particles; Spring spring; //パーリンノイズの値 float xoff = 0; float yoff = 1000; void setup(){ size(400, 300); box2d = new Box2DProcessing(this); box2d.createWorld(); box2d.listenForCollisions(); box = new Box(width/2, height/2); spring = new Spring(); spring.bind(width/2, height/2, box); particles = new ArrayList<Particle>(); } void draw(){ background(255); box2d.step(); //パーティクルの生成・追加 if(random(1) < 0.2){ float sz = random(4, 8); particles.add(new Particle(width/2, -20, sz)); } //パーリンノイズから座標を作る float x = noise(xoff)*width; float y = noise(yoff)*height; xoff += 0.01; yoff += 0.01; if(mousePressed){ spring.update(mouseX, mouseY); spring.display(); }else{ spring.update(x, y); } box.body.setAngularVelocity(0); //パーティクルに対する処理 for(int i = particles.size()-1; i >= 0; i--){ Particle p = particles.get(i); p.display(); if(p.done()){ particles.remove(i); } } box.display(); } //衝突したときの処理 void beginContact(Contact cp){ //フィクスチャの取得 Fixture f1 = cp.getFixtureA(); Fixture f2 = cp.getFixtureB(); //ボディの取得 Body b1 = f1.getBody(); Body b2 = f2.getBody(); //オブジェクトの取得 Object o1 = b1.getUserData(); Object o2 = b2.getUserData(); //オブジェクトの型の判定 if(o1.getClass() == Box.class){ Particle p = (Particle)o2; p.change(); }else if(o2.getClass() == Box.class){ Particle p = (Particle)o1; p.change(); } } void endContact(Contact cp){ }
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); body.setUserData(this); } //図形の描画 void display(){ Vec2 pos = box2d.getBodyPixelCoord(body); float a = body.getAngle(); rectMode(PConstants.CENTER); pushMatrix(); translate(pos.x, pos.y); rotate(-a); fill(175); stroke(0); 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(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 Particle{ Body body; float r; color col; //コンストラクタ Particle(float x, float y, float r_){ r = r_; makeBody(x, y, r); body.setUserData(this); col = color(127); } //衝突したら色を変更する void change(){ col = color(255, 0, 0); } 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(col); stroke(0); strokeWeight(2); ellipse(0, 0, r*2, r*2); line(0, 0, r, 0); popMatrix(); } void makeBody(float x, float y, float r){ //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.DYNAMIC; bd.position = 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.setAngularVelocity(random(-10, 10)); } }
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.0f * box.body.m_mass; md.frequencyHz = 5.0f; md.dampingRatio = 0.9f; 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の勉強にもなるので一石二鳥です。