Cocos2d-x: 違う親Nodeに乗っているSpriteを重ねて表示する
やりたいこと
Sprite* imgA
とSprite* imgB
が、
それぞれ違う場所にあるNodeの、しかもそのNodeから見て違う座標に乗っている場合(※)に、
imgAにimgBを重ねて表示したい@cocos2d-x
※このような状態から開始
AnchorPointはNodeもSpriteも0.5,0.5
前提
imgAおよびimgBのpositionを素直に取得すると、親Nodeのpositionから見てどこにいるか情報が帰ってくる
素直に取得する時
auto posImgA = imgA->getPosition();
↑こいつをそのままimgBにsetPositionしても、親Nodeのpositionが異なるので、うまくいかない
こうなっちゃう
逆に、それぞれのNodeの同じ位置に乗せたい〜とかならこれでいい
親Node同士のサイズが同じならだけど
やったこと
まずconvertToWorldSpace
を使ってimgAのpositionを絶対値に変換する
auto posImgAWorld = imgA->getParent()->convertToWorldSpace(imgA->getPosition());
上記の時、imgAの親Node(nodeA)からconvertToWorldSpaceを呼ばないとダメ
なのでgetParent()してある
そして得られたposAをimgBに設定したいのだが、
素直にsetPositonしてしまうと、
imgBの親Node(nodeB)から見てのpositionに上記の値が設定されてしまうので、
これは
imgB->setPosition(posImgAWorld);
こうなっちゃう
↑imgBが画面外のどっかにいってしまった、かなしい
ので、nodeBの相対値に座標を直さないとならない
convertToNodeSpace
を使用して変換する
imgB->setPosition(imgB->getParent()->convertToNodeSpace(posImgAWorld));
ここでもちゃんとimgB自身の親Nodeから呼ぶ
こうなって、完了
めでたしめでたし
というのを試したコード
auto nodeA = Node::create(); nodeA->setContentSize(Size(50.0f, 50.0f)); nodeA->setPosition(200.0f, 100.0f); nodeA->setAnchorPoint(Point(0.5f, 0.5f)); auto colorA = LayerGradient::create(Color4B(200, 200, 200, 255), Color4B(50, 50, 50, 255), Point(1, 1)); colorA->setContentSize(nodeA->getContentSize()); nodeA->addChild(colorA); auto imgA = Sprite::create("適当な画像1"); imgA->setPosition(Size(25.0f, 25.0f)); imgA->setAnchorPoint(Point(0.5f, 0.5f)); nodeA->addChild(imgA); this->addChild(nodeA); auto nodeB = Node::create(); nodeB->setContentSize(Size(50.0f, 50.0f)); nodeB->setPosition(270.0f, 100.0f); nodeB->setAnchorPoint(Point(0.5f, 0.5f)); nodeB->setAnchorPoint(Point(0.5f, 0.5f)); auto colorB = LayerGradient::create(Color4B(200, 200, 200, 255), Color4B(50, 50, 50, 255), Point(1, 1)); colorB->setContentSize(nodeB->getContentSize()); nodeB->addChild(colorB); auto imgB = Sprite::create("適当な画像2"); imgB->setPosition(Size(50.0f, 50.0f)); imgB->setAnchorPoint(Point(0.5f, 0.5f)); nodeB->addChild(imgB); this->addChild(nodeB); auto posImgA = imgA->getPosition(); auto posImgB = imgB->getPosition(); CCLOG("posImgA x:%f, y:%f", posImgA.x, posImgA.y); CCLOG("posImgB x:%f, y:%f", posImgB.x, posImgB.y); auto posImgAWorld = imgA->getParent()->convertToWorldSpace(imgA->getPosition()); CCLOG("posImgAWorldA x:%f, y:%f", posImgAWorld.x, posImgAWorld.y); auto pos = imgB->getParent()->convertToNodeSpace(posImgAWorld); imgB->setPosition(pos); CCLOG("pos x:%f, y:%f", pos.x, pos.y);
出力されるログはこうなる
posImgA x:25.000000, y:25.000000 posImgB x:50.000000, y:50.000000 posImgAWorldA x:200.000000, y:100.000000 pos x:-45.000000, y:25.000000
感想
親Nodeのpositionが同じだとか、親Nodeのサイズが画面サイズと同じだとかになっていれば途中の工程まででいけるので
そもそも画面の構成をめんどくさくないようにしろという話なのかもしれない