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

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

 メニュー

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

Processing:回転ジョイント

「The Nature of Code」から回転ジョイントについて取り上げます。回転ジョイントを設定すると物体を回転させられます。Processingでプログラムを書いて、動作を確認します。動作を確認できるところがProcessingの楽しいところです。

回転ジョイントの作成手順

  1. ボディを2つ用意する
  2. ジョイントを定義する
  3. ジョイントのプロパティを設定する
    • モーターを付けるか
    • モーターの速さ
    • トルク
  4. ジョイントの作成

回転ジョイント

以下は、回転ジョイントの参考例です。RevoluteJointクラスを利用します。

//Spinning Windmill
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;
Windmill windmill;
ArrayList<Particle> particles;

void setup(){
  size(640, 360);
  
  box2d = new Box2DProcessing(this);
  box2d.createWorld();
  
  windmill = new Windmill(width/2, 175);
  
  particles = new ArrayList<Particle>();
}

void draw(){
  background(255);
  box2d.step();
  
  //パーティクルの描画
  if(random(1) < 0.1){
    float sz = random(4, 8);
    particles.add(new Particle(random(width/2-100, width/2+100), -20, sz));
  }
  
  for(int i = particles.size()-1; i>=0; i--){
    Particle p = particles.get(i);
    p.display();
    if(p.done()){
      particles.remove(i);
    }
  }
  
  windmill.display();
  
  String status = "OFF";
  if(windmill.motorOn()){
    status = "ON";
  }
  
  fill(0);
  text("Click mouse to toggle motor.\nMotor:" + status, 10, height-30);
}

//クリックしたときの処理
void mousePressed(){
  windmill.toggleMotor();
}
class Windmill{
  RevoluteJoint joint;
  Box box1;
  Box box2;  
  
  //コンストラクタ
  Windmill(float x, float y){
    box1 = new Box(x, y-20, 120, 10, false);
    box2 = new Box(x, y, 10, 40, true);
    
    //回転ジョイントの定義
    RevoluteJointDef rjd = new RevoluteJointDef();
    rjd.initialize(box1.body, box2.body, box1.body.getWorldCenter());
    
    //モーターのチューニング
    rjd.motorSpeed = PI*2;
    rjd.maxMotorTorque = 1000.0;
    rjd.enableMotor = false;
    
    joint = (RevoluteJoint)box2d.world.createJoint(rjd);  
  }
  
  void toggleMotor(){
    joint.enableMotor(!joint.isMotorEnabled());
  }
  
  boolean motorOn(){
    return joint.isMotorEnabled();
  }
  
  //図形の描画
  void display(){
    box2.display();
    box1.display();
    
    //アンカーポイント
    Vec2 anchor = box2d.coordWorldToPixels(box1.body.getWorldCenter());
    fill(0);
    noStroke();
    ellipse(anchor.x, anchor.y, 8, 8);
  }
}
class Box{
  
  Body body;
  float w;
  float h;
  
  //コンストラクタ
  Box(float x, float y, float w_, float h_, boolean lock){
    w = w_;
    h = 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.position.set(box2d.coordPixelsToWorld(new Vec2(x, y)));
    if(lock){
      bd.type = BodyType.STATIC;
    }else{
      bd.type = BodyType.DYNAMIC;
    }
    body = box2d.createBody(bd);
    
    body.createFixture(fd);
    
    body.setLinearVelocity(new Vec2(random(-5, 5), random(2, 5)));
    body.setAngularVelocity(random(-5, 5));  
  }
    
  //図形の描画
  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();
  }
}
class Particle{
  Body body;
  float r;
  
  //コンストラクタ
  Particle(float x, float y, float r_){
    r = r_;
    
    makeBody(x, y, r);
    body.setUserData(this);
  }
  
  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();
  }
  
  //ボディの定義
  void makeBody(float x, float y, float r){
    //ボディの定義
    BodyDef bd = new BodyDef();
    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 = 2.0;
    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入門のまとめはこちらです。