cocos2d-x + Box2d PhysicsEditorで作った物理体を拡大/縮小してみる

Box2dの物理体を拡大/縮小したいことがありますが、
単純にSpriteをsetScaleしただけでは、見た目は変わっても、物理体は変わりません。

cocos2d-x + Box2d PhysicsEditorで作ったデータを読み込む - おかひろの雑記で作ったサンプルに、拡大/縮小処理を入れてみました。

今回使用したバージョン

  • Cocos2d-x 3.9
  • PhysicsEditor 1.5.2

動作するサンプルはこちら。 https://github.com/okahiro/Cocos2dxBox2d
(Cocos2d-xのフルプロジェクトなので容量大きいです)

createBlockメソッドで物理体を作成したらすぐにサイズも指定します。

void Box2dAndPEScene::createBlock(int x,int y)
{
	_blockNo++;
	
	// ブロックの名前(PhysicsEditer上でつけた名前)
	std::string blockName = "";
	// Noによってブロックを変える
	switch(_blockNo % 4)
	{
		case 0:
			blockName = "circle";
			break;
		case 1:
			blockName = "cross";
			break;
		case 2:
			blockName = "square";
			break;
		case 3:
			blockName = "triangle";
			break;
		default:
			blockName = "circle";
			break;
	}
	
	// Sprite
	Sprite *block = Sprite::create(StringUtils::format("res/%s.png",blockName.c_str()));
	block->setTag(_blockNo);		// ブロックに番号をつける
	this->addChild(block);
	
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;
	bodyDef.position.Set(x / PTM_RATIO,y / PTM_RATIO);
	
	b2Body *body = this->_world->CreateBody(&bodyDef);
	gbox2d::GB2ShapeCache::getInstance()->addFixturesToBody(body, blockName);	// bodyに、plist上の指定の物理体情報でFixture作成
	body->SetUserData(block);
	
	// AnchorPointを取得して設定
	block->setAnchorPoint(gbox2d::GB2ShapeCache::getInstance()->anchorPointForShape(blockName));
	
	// ブロックのサイズ変更
	// 大きさ 0.75倍、等倍、1.25倍
	float scale = 0.75f + ((int)(CCRANDOM_0_1() * 100) % 3) * 0.25f;
	
	if(scale != 1.0f)
	{
		// 物理構造のスケーリング
		for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext())
		{
			b2Shape *shape = f->GetShape();
			if(shape->GetType() == b2Shape::e_circle)
			{
				// 円の場合は半径をスケール
				body->GetFixtureList()->GetShape()->m_radius *= scale;
			}
			else
			{
				// 円以外の場合
				b2PolygonShape *poly = (b2PolygonShape*)shape;
				int vCount = poly->GetVertexCount();	// 頂点の数
				b2Vec2 vertices[b2_maxPolygonVertices];
				// 全ての頂点にscaleをかける
				for(int i = 0; i < vCount; i++)
				{
					b2Vec2 v = poly->GetVertex(i);
					vertices[i].x = v.x * scale;
					vertices[i].y = v.y * scale;
				}
				// 新しい頂点を設定
				poly->Set(vertices, vCount);
			}
		}
		
		// スプライトもサイズ変更
		block->setScale(scale);
	}
	
	CCLOG("■ブロック%dを作成しました。サイズ:%f",_blockNo,scale);
}

bodyからb2Fixtureを取得し、さらにb2Shapeを取得します。
形が円の場合は単純に半径に倍率をかけ、そうでないときは全頂点を取得して倍率をかけます。