cocos2d-x 3.0 beta で物理エンジンを利用する

はじめに

3.x 系で追加された PhysicsWorld や PhysicsBody などのクラスを利用することで、
chipmunk に依存しないコードで、物理を利用できるようです。

物理世界(PhysicsWorld)の生成

PhysicsWorld は、Scene クラスが持っています。
Scene::create() の代わりに Scene::createWithPhysics() とすることで、
PhysicsWorld を持ったシーンを生成することができます。

	auto scene = Scene::createWithPhysics();

剛体(PhysicsBody)の生成

まずは、他の剛体が無限に落下しないように、
画面下部あたりに地面スプライトを用意します。
(以下のコードは HelloWorld::init() 内に追加しています。)

{
	// スプライトの生成と追加
	auto pSprite = Sprite::create();
	pSprite->setContentSize(Size(visibleSize.width, 10));
	pSprite->setPosition(Point(visibleSize.width / 2, 0));
	addChild(pSprite);

	// 剛体の生成
	auto material = PHYSICSBODY_MATERIAL_DEFAULT;
	material.density     = 1.0f; // 密度
	material.restitution = 0.9f; // 反発係数
	material.friction    = 0.5f; // 摩擦係数
	auto pBody = PhysicsBody::createBox(pSprite->getContentSize(), material);
	pBody->setDynamic(false); // 地面は重力の影響を受けない

	// スプライトに剛体を関連付ける
	pSprite->setPhysicsBody(pBody);
}

さらに、適当な剛体スプライトを追加してみます。

{
	// テキストスプライトの生成と追加
	auto pSprite = LabelTTF::create("Physics Sprite", "Arial", 24);
	pSprite->setPosition(Point(visibleSize.width / 2, 200.0f));
	addChild(pSprite);

	// 剛体の生成
	auto material = PHYSICSBODY_MATERIAL_DEFAULT;
	material.density     = 1.0f; // 密度
	material.restitution = 0.6f; // 反発係数
	material.friction    = 0.5f; // 摩擦係数
	auto pBody = PhysicsBody::createBox(pSprite->getContentSize(), material);
	pBody->setMass(1.0f); // 重さ
	pBody->setMoment(1000.0f); // モーメント(大きいほど回転しにくい)

	// テキストスプライトに剛体を関連付ける
	pSprite->setPhysicsBody(pBody);

	// 適当な力を与えて回転させてみる
	pBody->applyImpulse(Vect(0.0f, 10.0f), Point(100.0f, 0.0f));
}

実行

"Physics Sprite" というテキストが重力によって落下して、
画面下にある地面にあたって跳ねます。
以下は win32 版のキャプチャですが、android 版も同じように動作します。

f:id:voidbox:20140125190807p:plain