元Webデザイナー兼コーダーの備忘録

ウェブデザインやプログラミング、ブログのカスタマイズなどについてアウトプットしています。

 メニュー

» HTML入門のまとめはこちらです。

Processing:衝突イベントの基礎

「The Nature of Code」から衝突イベントの基礎について取り上げます。物体が衝突したときの処理の基本的な書き方を見ていきます。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。

衝突イベントのコールバック

衝突イベントのコールバックは、以下の4つがあります。

  • beginContact()
  • endContact()
  • preSolve()
  • postSolve()

衝突イベントの基礎

2つの物体が衝突したら色を変更します。以下は、その参考例です。

//CollisionListening
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.change();
    Particle p2 = (Particle)o2;
    p2.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;
  
  //コンストラクタ
  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));    
  }  
}

まとめ

「The Nature of Code」から衝突イベントの基礎について取り上げました。引き続き、「The Nature of Code」の内容を勉強します。

参考書籍

Javaの勉強にもなるので一石二鳥です。

» HTML入門のまとめはこちらです。