「The Nature of Code」から衝突イベントと物体の削除について取り上げます。物体が衝突したらその物体を消します。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。
衝突イベントと物体の削除
パーティクルが地面に当たったら、パーティクルの色を変更します。パーティクル同士が当たったら、消します。以下は、その参考例です。
//CollisionListeningDeletionExercise 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; ArrayList<Particle> particles; Boundary wall; void setup(){ size(200, 200); box2d = new Box2DProcessing(this); box2d.createWorld(); //collision listening box2d.listenForCollisions(); particles = new ArrayList<Particle>(); wall = new Boundary(width/2, height-5, width, 10); } void draw(){ background(255); box2d.step(); //パーティクルの生成・追加 if(random(1) < 0.1){ float sz = random(4, 8); particles.add(new Particle(random(width), 20, sz)); } //すべてのパーティクルを走査する for(int i = particles.size()-1; i >= 0; i--){ Particle p = particles.get(i); p.display(); //パーティクルの描画 if(p.done()){ particles.remove(i); //パーティクルの削除 } } wall.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() == Particle.class && o2.getClass() == Particle.class){ Particle p1 = (Particle)o1; p1.delete(); Particle p2 = (Particle)o2; p2.delete(); } //境界と衝突したときの処理 if(o1.getClass() == Boundary.class){ Particle p = (Particle)o2; p.change(); } //境界と衝突したときの処理 if(o2.getClass() == Boundary.class){ Particle p = (Particle)o1; p.change(); } } void endContact(Contact cp){ }
class Boundary{ float x; float y; float w; float h; Body b; //コンストラクタ Boundary(float x_, float y_, float w_, float h_){ x = x_; y = y_; w = w_; h = h_; //ボディの定義 BodyDef bd = new BodyDef(); bd.type = BodyType.STATIC; 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); b.setUserData(this); } //図形の描画 void display(){ fill(0); stroke(0); rectMode(CENTER); rect(x, y, w, h); } }
class Particle{ Body body; float r; color col; boolean delete = false; //コンストラクタ Particle(float x, float y, float r_){ r = r_; makeBody(x, y, r); body.setUserData(this); col = color(127); } void delete(){ delete = true; } //色を変更する 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 || delete){ 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)); } }
まとめ
「The Nature of Code」から衝突イベントと物体の削除について取り上げました。物体が衝突したらその物体を消すことができました。引き続き、「The Nature of Code」の内容を勉強します。
参考書籍
※Javaの勉強にもなるので一石二鳥です。