※サンプルコードを動かす方法はこちら
その中でも興味を引いたのは19. Effects - Advanced にあったJumpy Lens3D
これを使えば面白いものが作れそう!
実際にどのような処理を行っているのかコードを読んだところ
void Effect4::onEnter()
{
EffectAdvanceBaseTest::onEnter();
//Node* gridNode = NodeGrid::create();
auto lens = Lens3D::create(10, Size(32,24), Vec2(100,180), 150);
auto move = JumpBy::create(5, Vec2(380,0), 100, 4);
auto move_back = move->reverse();
auto seq = Sequence::create( move, move_back, nullptr);
/* In cocos2d-iphone, the type of action's target is 'id', so it supports using the instance of 'Lens3D' as its target.
While in cocos2d-x, the target of action only supports Node or its subclass,
so we make an encapsulation for Lens3D to achieve that.
*/
auto director = Director::getInstance();
auto pTarget = Lens3DTarget::create(lens);
// Please make sure the target been added to its parent.
this->addChild(pTarget);
//gridNode->addChild(pTarget);
director->getActionManager()->addAction(seq, pTarget, false);
_bgNode->runAction( lens );
}
Lens3Dのインスタンスを作成してそれをLens3DTargetというNodeを継承したクラスでラップしてActionManagerへ渡している。
このLens3DTargetは本当にただラップしているだけ、ソース上の説明にある通りActionの操作対象はNodeかそのサブクラスである必要があるためらしい。JumpByからsetPosition()とgetPosition()が呼ばれたらメンバであるLens3Dの同メソッドを呼んでいる。
class Lens3DTarget : public Node { public: virtual void setPosition(const Vec2& var) { _lens3D->setPosition(var); } virtual const Vec2& getPosition() const { return _lens3D->getPosition(); } static Lens3DTarget* create(Lens3D* pAction) { Lens3DTarget* pRet = new (std::nothrow) Lens3DTarget(); pRet->_lens3D = pAction; pRet->autorelease(); return pRet; } private: Lens3DTarget() : _lens3D(nullptr) {} Lens3D* _lens3D; };
基本は分かったので試しにSeaquenceに渡すmoveを一つ増やしてみたところ、
追加分のmoveが動かない・・・。
理由も全く分からない。
そして、デバックを繰り返したところやっと理由が判明!
Lens3D::create(10, Size(32,24), Vec2(100,180), 150)
durationとして10を渡していたのが原因だった。
| static |
Create the action with center position, radius, a grid size and duration.
- Parameters
duration Specify the duration of the Lens3D action. It's a value in seconds. gridSize Specify the size of the grid. position Specify the center position of the lens. radius Specify the radius of the lens.
このdurationはこのLens3Dの存在時間を指定している。
この値はActionManagerはupdate()の中で操作しているactionが終わったかどうかをisDone()問いうメソッドを通して確認をしている。
このisDoneでは実際に経過した時間と指定したdurationを比べてdurationが経過した場合このActionは終わったとしてtrueを返すため、ActionManagerよりremoveAction(Lens3Dのインスタンス)でLens3Dが管理対象から外されてしまう。
そのため、一回のJumpByが5秒であるmoveの3回目は丁度タイミングよく実行されなくなる。
あー、ここまで調べるのに3日以上かかってしまった。。。