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を取得します。
形が円の場合は単純に半径に倍率をかけ、そうでないときは全頂点を取得して倍率をかけます。