読者です 読者をやめる 読者になる 読者になる

フニゲの開発日記

Electronとか...

RUBEで作ったシーンを表示する

RUBE cocos2d-html5 Box2D


R.U.B.E Box2D Editorはマジで使えるBox2Dエディタ(Really Useful Box2D Editor)。¥3000。無料の体験版もある。

f:id:funige:20130912221750p:plain

完成度が高くて、とにかく使っていて気持ちのいいツールだ。
玄人好みの操作系で最初戸惑うのだが、詳しいチュートリアルビデオがあるので我慢して見ていれば頭に入ると思う。

出力はJSONなので、当然cocos2d-html5にも使える。
前に作ったサンプルを改造してRUBEで作ったワールドを表示してみよう。

// boot-html5.js
    ...
    appFiles:[
        './Box2dWeb-2.1.a.3.min.js',
        './loadrube.js', // <- 追加
        ....

Box2dWeb.jsの他に、RUBEのサンプルローダーに含まれるloadrube.jsを読み込んでおく。

前は壁とか地面とか一枚ずつ手作業で定義していたけど、RUBEのデータを読み込むだけなら一行で書ける。

// game.js
var Game = cc.Layer.extend({
    world:null,
    ctor:function () {
        this._super();


        this.world = loadWorldFromRUBE(carJSON); // スッキリ!


        this.setBox2dDebug();
        this.scheduleUpdate();
    }, 

    // デバッグ表示の準備
    setBox2dDebug:function () {
        var debugDraw = new b2DebugDraw();
        debugDraw.SetSprite(document.getElementById("debugDraw").getContext("2d"));
        debugDraw.SetDrawScale(PTM_RATIO);
        debugDraw.SetFillAlpha(0.3);
        debugDraw.SetAlpha(1);
        debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit);

        this.world.SetDebugDraw(debugDraw);
    },
    ....

    update:function (dt) {
        this.world.Step(dt, 8, 1);
        this.world.DrawDebugData(); // デバッグ表示

        for (var b = this.world.GetBodyList(); b; b = b.GetNext()) {
            ....
            if (b.name == "rear wheel") {
                b.SetAngularVelocity(-5); // ついでに車を動かすよ
            }
        }
    },

前回デバッグ表示について書くのを忘れていたので書いておく。
Box2Dのデバッグ表示はcocos2dを通さずに直接canvasに描画して、cocos2dのゲーム画面にぴったり重ねて表示している。

<!-- index.html -->
...
<canvas id="gameCanvas" width="480" height="320"></canvas>
<canvas id="debugDraw" width="480" height="320"
  style="position:absolute; top:0; left:0;
         pointer-events:none;
         -webkit-transform:scaleY(-1); -moz-transform:scaleY(-1);"></canvas>
...

IEは面倒なので非対応。まあデバッグ用なので自分の環境で動けばいいのだ。

あとBox2Dのクラス名を短く書けるようにエイリアスを用意する。
これがないとloadrube.jsが動かない。
サンプルローダーのtestbed.jsからカットアンドペースト

// グローバルなのでどこか適当な場所で定義
var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
      b2EdgeChainDef = Box2D.Collision.Shapes.b2EdgeChainDef,
      b2EdgeShape = Box2D.Collision.Shapes.b2EdgeShape,
      b2MassData = Box2D.Collision.Shapes.b2MassData,
      b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
      b2Shape = Box2D.Collision.Shapes.b2Shape,
      b2CircleContact = Box2D.Dynamics.Contacts.b2CircleContact,
      b2Contact = Box2D.Dynamics.Contacts.b2Contact,
      b2ContactConstraint = Box2D.Dynamics.Contacts.b2ContactConstraint,
      b2ContactConstraintPoint = Box2D.Dynamics.Contacts.b2ContactConstraintPoint,
      b2ContactEdge = Box2D.Dynamics.Contacts.b2ContactEdge,
      b2ContactFactory = Box2D.Dynamics.Contacts.b2ContactFactory,
      b2ContactRegister = Box2D.Dynamics.Contacts.b2ContactRegister,
      b2ContactResult = Box2D.Dynamics.Contacts.b2ContactResult,
      b2ContactSolver = Box2D.Dynamics.Contacts.b2ContactSolver,
      b2EdgeAndCircleContact = Box2D.Dynamics.Contacts.b2EdgeAndCircleContact,
      b2NullContact = Box2D.Dynamics.Contacts.b2NullContact,
      b2PolyAndCircleContact = Box2D.Dynamics.Contacts.b2PolyAndCircleContact,
      b2PolyAndEdgeContact = Box2D.Dynamics.Contacts.b2PolyAndEdgeContact,
      b2PolygonContact = Box2D.Dynamics.Contacts.b2PolygonContact,
      b2PositionSolverManifold = Box2D.Dynamics.Contacts.b2PositionSolverManifold,
      b2Body = Box2D.Dynamics.b2Body,
      b2_staticBody = Box2D.Dynamics.b2Body.b2_staticBody,
      b2_kinematicBody = Box2D.Dynamics.b2Body.b2_kinematicBody,
      b2_dynamicBody = Box2D.Dynamics.b2Body.b2_dynamicBody,
      b2BodyDef = Box2D.Dynamics.b2BodyDef,
      b2ContactFilter = Box2D.Dynamics.b2ContactFilter,
      b2ContactImpulse = Box2D.Dynamics.b2ContactImpulse,
      b2ContactListener = Box2D.Dynamics.b2ContactListener,
      b2ContactManager = Box2D.Dynamics.b2ContactManager,
      b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
      b2DestructionListener = Box2D.Dynamics.b2DestructionListener,
      b2FilterData = Box2D.Dynamics.b2FilterData,
      b2Fixture = Box2D.Dynamics.b2Fixture,
      b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
      b2Island = Box2D.Dynamics.b2Island,
      b2TimeStep = Box2D.Dynamics.b2TimeStep,
      b2World = Box2D.Dynamics.b2World,
      b2Color = Box2D.Common.b2Color,
      b2internal = Box2D.Common.b2internal,
      b2Settings = Box2D.Common.b2Settings,
      b2Mat22 = Box2D.Common.Math.b2Mat22,
      b2Mat33 = Box2D.Common.Math.b2Mat33,
      b2Math = Box2D.Common.Math.b2Math,
      b2Sweep = Box2D.Common.Math.b2Sweep,
      b2Transform = Box2D.Common.Math.b2Transform,
      b2Vec2 = Box2D.Common.Math.b2Vec2,
      b2Vec3 = Box2D.Common.Math.b2Vec3,
      b2AABB = Box2D.Collision.b2AABB,
      b2Bound = Box2D.Collision.b2Bound,
      b2BoundValues = Box2D.Collision.b2BoundValues,
      b2Collision = Box2D.Collision.b2Collision,
      b2ContactID = Box2D.Collision.b2ContactID,
      b2ContactPoint = Box2D.Collision.b2ContactPoint,
      b2Distance = Box2D.Collision.b2Distance,
      b2DistanceInput = Box2D.Collision.b2DistanceInput,
      b2DistanceOutput = Box2D.Collision.b2DistanceOutput,
      b2DistanceProxy = Box2D.Collision.b2DistanceProxy,
      b2DynamicTree = Box2D.Collision.b2DynamicTree,
      b2DynamicTreeBroadPhase = Box2D.Collision.b2DynamicTreeBroadPhase,
      b2DynamicTreeNode = Box2D.Collision.b2DynamicTreeNode,
      b2DynamicTreePair = Box2D.Collision.b2DynamicTreePair,
      b2Manifold = Box2D.Collision.b2Manifold,
      b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint,
      b2Point = Box2D.Collision.b2Point,
      b2RayCastInput = Box2D.Collision.b2RayCastInput,
      b2RayCastOutput = Box2D.Collision.b2RayCastOutput,
      b2Segment = Box2D.Collision.b2Segment,
      b2SeparationFunction = Box2D.Collision.b2SeparationFunction,
      b2Simplex = Box2D.Collision.b2Simplex,
      b2SimplexCache = Box2D.Collision.b2SimplexCache,
      b2SimplexVertex = Box2D.Collision.b2SimplexVertex,
      b2TimeOfImpact = Box2D.Collision.b2TimeOfImpact,
      b2TOIInput = Box2D.Collision.b2TOIInput,
      b2WorldManifold = Box2D.Collision.b2WorldManifold,
      ClipVertex = Box2D.Collision.ClipVertex,
      Features = Box2D.Collision.Features,
      IBroadPhase = Box2D.Collision.IBroadPhase,
      b2Joint = Box2D.Dynamics.Joints.b2Joint,
      b2JointDef = Box2D.Dynamics.Joints.b2JointDef,
      b2JointEdge = Box2D.Dynamics.Joints.b2JointEdge,
      b2LineJoint = Box2D.Dynamics.Joints.b2LineJoint,
      b2LineJointDef = Box2D.Dynamics.Joints.b2LineJointDef,
      b2MouseJoint = Box2D.Dynamics.Joints.b2MouseJoint,
      b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef,
      b2PrismaticJoint = Box2D.Dynamics.Joints.b2PrismaticJoint,
      b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef,
      b2PulleyJoint = Box2D.Dynamics.Joints.b2PulleyJoint,
      b2PulleyJointDef = Box2D.Dynamics.Joints.b2PulleyJointDef,
      b2RevoluteJoint = Box2D.Dynamics.Joints.b2RevoluteJoint,
      b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef,
      b2WeldJoint = Box2D.Dynamics.Joints.b2WeldJoint,
      b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef,
      b2DistanceJoint = Box2D.Dynamics.Joints.b2DistanceJoint,
      b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef,
      b2FrictionJoint = Box2D.Dynamics.Joints.b2FrictionJoint,
      b2FrictionJointDef = Box2D.Dynamics.Joints.b2FrictionJointDef;

だらだら長いけど、やってることは単純だ。

で、RUBEのデータなのだが……JSONファイルを動的に読み込む所がうまく書けなかった。本当はcc.FileUtilsとか使うんだと思うんだけど。
RUBEからQuick Exportで出力されるJSONファイルはこんな感じ。

{
	"allowSleep" : true,
	"autoClearForces" : true,
	"body" : 
	[
        ....

しょうがないので、変数に代入してソースファイルとして読み込む。

var carJSON = { // <- 修正
	"allowSleep" : true,
	"autoClearForces" : true,
	"body" : 
	[
        ...

これを冒頭のboot-html5.jsに追加すればOK。

動くサンプルはこちら

f:id:funige:20130912215930p:plain

広告を非表示にする