Objectに画像を貼り付けてみよう

画像ファイルを適当に作成

今回は例として以下のファイルを使う

  • clione_circle.png
_images/clione_circle.png
  • clione_squere.png
_images/clione_squere.png

ディレクトリ構造追加

.
├── img
│   ├── clione_circle.png
│   └── clione_squere.png
├── index.html
└── js
    ├── Box2dWeb-2.1.a.3.min.js
    ├── jquery-2.1.1.min.js
    └── main.js

画像を読み込み

var world = new b2.World(
    new b2.Vec2(0, 9.8), // 重力方向
    true                 // Sleepの可否
);

var worldHeight = 600;
var worldWidth = 800;
var worldScale = 30.0;
var circleImg = new Image();
var boxImg = new Image();
circleImg.src = './img/clione_circle.png';
boxImg.src = './img/clione_squere.png';

BodyのUserDataを使って、追加情報を付与

// 円形オブジェクトの設置
bodyDef.position.x = x / worldScale;
bodyDef.position.y = y / worldScale;
bodyDef.userData = {shape_type: 'circle', img: circleImg, radius: r};
world.CreateBody(bodyDef).CreateFixture(fixDef);
// 四角形オブジェクトの設置
fixDef.shape.SetAsBox(halfWidth / worldScale, halfHeight / worldScale );
bodyDef.position.Set(x / worldScale, y / worldScale );
bodyDef.userData = {shape_type: 'box', img: boxImg, width: w, height: h};
world.CreateBody(bodyDef).CreateFixture(fixDef);

画像を描画

function run() {
  world.Step(1 / 60.0, 10, 10);
  world.DrawDebugData();
  world.ClearForces();

  var context = document.getElementById('canvas').getContext('2d');
  for ( var bodyItem = world.GetBodyList();
        bodyItem;
        bodyItem = bodyItem.GetNext() ) {
    if ( bodyItem.GetType() == b2.Body.b2_dynamicBody ) {
      var position = bodyItem.GetPosition();
      var userData = bodyItem.GetUserData();

      context.save();
      if ( userData && userData.img && userData.img.complete ) {
        if ( userData.shape_type && userData.shape_type == 'circle' ) {
          var slideX = position.x * worldScale;
          var slideY = position.y * worldScale;

          context.translate(slideX, slideY);
          context.rotate( bodyItem.GetAngle() );
          context.drawImage( userData.img, -userData.radius, -userData.radius);
        }
        if ( userData.shape_type && userData.shape_type == 'box' ) {
          var slideX = position.x * worldScale;
          var slideY = position.y * worldScale;

          context.translate(slideX, slideY);
          context.rotate( bodyItem.GetAngle() );
          context.drawImage( userData.img, -userData.width / 2.0, -userData.height / 2.0);
        }
      }
      context.restore();
    }
  }
}

Demo

Demo

全文(JavaScript)

var b2 = {
    Vec2          : Box2D.Common.Math.b2Vec2
  , AABB          : Box2D.Collision.b2AABB
  , BodyDef       : Box2D.Dynamics.b2BodyDef
  , Body          : Box2D.Dynamics.b2Body
  , FixtureDef    : Box2D.Dynamics.b2FixtureDef
  , Fixture       : Box2D.Dynamics.b2Fixture
  , World         : Box2D.Dynamics.b2World
  , MassData      : Box2D.Collision.Shapes.b2MassData
  , PolygonShape  : Box2D.Collision.Shapes.b2PolygonShape
  , CircleShape   : Box2D.Collision.Shapes.b2CircleShape
  , DebugDraw     : Box2D.Dynamics.b2DebugDraw
  , MouseJointDef : Box2D.Dynamics.Joints.b2MouseJointDef
};

var world = new b2.World(
    new b2.Vec2(0, 9.8), // 重力方向
    true                 // Sleepの可否
);

var worldHeight = 600;
var worldWidth = 800;
var worldScale = 30.0;
var circleImg = new Image();
var boxImg = new Image();
circleImg.src = './img/clione_circle.png';
boxImg.src = './img/clione_squere.png';

function getDebugDraw() {
  var debugDraw = new b2.DebugDraw();
  debugDraw.SetSprite(document.getElementById('canvas').getContext('2d'));
  debugDraw.SetDrawScale(worldScale);
  debugDraw.SetFillAlpha(0.5);
  debugDraw.SetLineThickness(1.0);
  debugDraw.SetFlags(b2.DebugDraw.e_shapeBit);
  return debugDraw;
}


function createFloor(world) {
  var bodyDef = new b2.BodyDef;
  bodyDef.type = b2.Body.b2_staticBody;

  // オブジェクトの設定
  var fixDef = new b2.FixtureDef;
  fixDef.density = 1.0;     // 密度
  fixDef.friction = 0.5;    // 摩擦係数
  fixDef.restitution = 0.4; // 反発係数

  // 床の設置
  fixDef.shape = new b2.PolygonShape;
  fixDef.shape.SetAsBox(worldWidth / worldScale, 2.0 / worldScale );
  bodyDef.position.Set(0, (worldHeight - 2) / worldScale);
  world.CreateBody(bodyDef).CreateFixture(fixDef);
}

function createCircle(world, x, y, r) {
  var bodyDef = new b2.BodyDef;
  bodyDef.type = b2.Body.b2_dynamicBody;

  // オブジェクトの設定
  var fixDef = new b2.FixtureDef;
  fixDef.density  = 1.0;     // 密度
  fixDef.friction = 0.5;     // 摩擦係数
  fixDef.restitution = 0.4;  // 反発係数
  fixDef.shape = new b2.CircleShape( r / worldScale );

  // 円形オブジェクトの設置
  bodyDef.position.x = x / worldScale;
  bodyDef.position.y = y / worldScale;
  bodyDef.userData = {shape_type: 'circle', img: circleImg, radius: r};
  world.CreateBody(bodyDef).CreateFixture(fixDef);
}

function createBox(world, x, y, w, h) {
  var bodyDef = new b2.BodyDef;
  bodyDef.type = b2.Body.b2_dynamicBody;

  var halfWidth = w / 2.0;
  var halfHeight = h / 2.0;

  // オブジェクトの設定
  var fixDef = new b2.FixtureDef;
  fixDef.density  = 1.0;     // 密度
  fixDef.friction = 0.5;     // 摩擦係数
  fixDef.restitution = 0.4;  // 反発係数
  fixDef.shape = new b2.PolygonShape;

  // 四角形オブジェクトの設置
  fixDef.shape.SetAsBox(halfWidth / worldScale, halfHeight / worldScale );
  bodyDef.position.Set(x / worldScale, y / worldScale );
  bodyDef.userData = {shape_type: 'box', img: boxImg, width: w, height: h};
  world.CreateBody(bodyDef).CreateFixture(fixDef);
}

function randInt(maxValue) {
  return 0|(Math.random() * maxValue);
}

$('#btn1').click(function() {
  var circleRadius = 40;
  createCircle(world,
               circleRadius + randInt(worldWidth - 2 * circleRadius),
               -circleRadius,
               circleRadius);
});

$('#btn2').click(function() {
  var boxLength = 80;
  createBox(world,
            boxLength / 2.0 + randInt(worldWidth - boxLength),
            -boxLength,
            boxLength,
            boxLength);
});

$('#btn3').click(function () {
  deleteBodyArray = [];
  for ( var bodyItem = world.GetBodyList();
        bodyItem;
        bodyItem = bodyItem.GetNext() )
  {
    if ( bodyItem.GetType() == b2.Body.b2_dynamicBody ) {
      deleteBodyArray.push(bodyItem);
    }
  }

  for ( var i in deleteBodyArray ) {
    world.DestroyBody( deleteBodyArray[i] );
  }
});

function run() {
  world.Step(1 / 60.0, 10, 10);
  world.DrawDebugData();
  world.ClearForces();

  var context = document.getElementById('canvas').getContext('2d');
  for ( var bodyItem = world.GetBodyList();
        bodyItem;
        bodyItem = bodyItem.GetNext() ) {
    if ( bodyItem.GetType() == b2.Body.b2_dynamicBody ) {
      var position = bodyItem.GetPosition();
      var userData = bodyItem.GetUserData();

      context.save();
      if ( userData && userData.img && userData.img.complete ) {
        if ( userData.shape_type && userData.shape_type == 'circle' ) {
          var slideX = position.x * worldScale;
          var slideY = position.y * worldScale;

          context.translate(slideX, slideY);
          context.rotate( bodyItem.GetAngle() );
          context.drawImage( userData.img, -userData.radius, -userData.radius);
        }
        if ( userData.shape_type && userData.shape_type == 'box' ) {
          var slideX = position.x * worldScale;
          var slideY = position.y * worldScale;

          context.translate(slideX, slideY);
          context.rotate( bodyItem.GetAngle() );
          context.drawImage( userData.img, -userData.width / 2.0, -userData.height / 2.0);
        }
      }
      context.restore();
    }
  }
}

function init() {
  createFloor(world);
  for (i = 0; i < 10; i++) {
    //createCircle(world, i*80+40, i*40, 40);
    createBox(world, i*80+40, i*40, 79, 79);
  }
  world.SetDebugDraw(getDebugDraw());
}

function start() {
  init();
  window.setInterval(run, 1000 / 60.0);
}