狂ったお茶会のlog

後で起きる自分のためのメモ

Cocos2d-x: 違う親Nodeに乗っているSpriteを重ねて表示する

やりたいこと

Sprite* imgASprite* imgBが、
それぞれ違う場所にあるNodeの、しかもそのNodeから見て違う座標に乗っている場合(※)に、
imgAにimgBを重ねて表示したい@cocos2d-x

※このような状態から開始
f:id:dormouse666:20160709224437p:plain
AnchorPointはNodeもSpriteも0.5,0.5


前提

imgAおよびimgBのpositionを素直に取得すると、親Nodeのpositionから見てどこにいるか情報が帰ってくる

素直に取得する時

auto posImgA = imgA->getPosition();

↑こいつをそのままimgBにsetPositionしても、親Nodeのpositionが異なるので、うまくいかない

こうなっちゃう
f:id:dormouse666:20160709224507p:plain

逆に、それぞれの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);

こうなっちゃう
f:id:dormouse666:20160709224716p:plain

↑imgBが画面外のどっかにいってしまった、かなしい


ので、nodeBの相対値に座標を直さないとならない
convertToNodeSpaceを使用して変換する

imgB->setPosition(imgB->getParent()->convertToNodeSpace(posImgAWorld));

ここでもちゃんとimgB自身の親Nodeから呼ぶ

こうなって、完了
f:id:dormouse666:20160709224630p:plain

めでたしめでたし


というのを試したコード

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のサイズが画面サイズと同じだとかになっていれば途中の工程まででいけるので
そもそも画面の構成をめんどくさくないようにしろという話なのかもしれない