Help us understand the problem. What is going on with this article?

cocos2d-xのrunActionについて

More than 5 years have passed since last update.

今年の春〜夏頃からcocos2d-xを本格的にはじめることになりました。
そもそもC++11の知識が必要であったりAndroid NDKで一部ビルドが通らなかったり、、
いろいろなことがありましたが一番つまづいたcocos2d-xのアニメーションについて書きます。

その1 いくつかのActionを呼び出す時の話

3つのスプライトを動かしたい場合、同時に動かしたい場合、初心者の時に
以下のように記述していました。

1.1
auto circle = Sprite::create("circle.png");
auto triangle = Sprite::create("triangle.png");
auto square = Sprite::create("square.png");

this->addChild(circle);
this->addChild(triangle);
this->addChild(square);

circle->runAction(MoveTo::create(0.3, Vec2(100, 100)));
triangle->runAction(MoveTo::create(0.3, Vec2(100, 100)));
square->runAction(MoveTo::create(0.3, Vec2(100, 100)));

が、、
ActionをとめたいときやAction完了のcallbackを取りたい場合、
上記の書き方はあまり適してはいませんでした。
上記のようなActionをしたい場合は以下のようにも書くことができます。

1.2
this->runAction(Spawn::create(TargetedAction::create(circle, MoveTo::create(0.3, Vec2(100, 100)),
                              TargetedAction::create(triangle, MoveTo::create(0.3, Vec2(100, 100)),
                              TargetedAction::create(square, MoveTo::create(0.3, Vec2(100, 100)),
                              nullptr));

1.2の書き方だとアニメーションを止めたい場合、this->stopAllActions()で一括で止めることができます。
逆にその2ですでにthis->runAction()を行っている場合、Actionが上書きされてしまいます。

TargetedActionはとても有用でActionの可読性があがるだけでなく、
どのNodeがどのActionを管理しているのか意識することができます。

その2 いくつかのActionを呼び出される時の話

以下の様な場合がありました。

・エフェクトAを再生する
・エフェクトAのアクション完了時にエフェクトBとCを同時再生する
・エフェクトBかCのアクション完了時にエフェクトDを再生する
・ここのエフェクトだけちょっとスロー再生で

このときにエフェクトのクラスをどう書くかかを迷ったのですが、
もろもろあって以下の点をおさえるとすっきりしました。(個人の感想です)

・そのクラスからActionの処理を取得できること
・そのクラスからActionの処理を投げっぱなしにできること
・durationは外出し

具体的にはこんなかんじのを書くと

HogeEffect.cpp


FiniteAction* HogeEffect::getPlayAction(float duration)
{
    return TargetedAction::create(this, MoveTo::create(duration, Vec2(100, 100)),
}

void HogeEffect::runPlayAction(float duration)
{
    this->runAction(getPlayAction(duration));
}

以下のように呼び出すことができます

this->runAction(Sequence::create(effectA->getPlayAction(0.1f),
                                 Spawn::create(effectB->getPlayAction(0.2f),
                                               effectC->getPlayAction(0.3f),
                                               nullptr),
                                 effectD->getPlayAction(0.4f),
                                 nullptr));

Actionには多くの派生クラスがありますが、
個人的にはSpawn、Sequenceをよく使うのでFiniteAction*で定義していました。

スクリーンショット 2014-12-18 2.52.46.png

http://www.cocos2d-x.org/reference/native-cpp/V3.3rc0/db/d61/classcocos2d_1_1_action.html
http://www.cocos2d-x.org/reference/native-cpp/V3.3rc0/dc/df1/classcocos2d_1_1_spawn.html
http://www.cocos2d-x.org/reference/native-cpp/V3.3rc0/d7/d30/classcocos2d_1_1_sequence.html

その3 他の言語などと比べた話 (+ラッパーつくりました)

言語/ツール 名前 特徴
swift SKActionクラス全般 cocos2dとほぼ同じ
Unity標準 Animation カーブアニメーション指定。Animator(Mecanim)との連携が強力
Unity Plugin iTween http://itween.pixelplacement.com/index.php
ActionScript BetweenAS3 http://www.libspark.org/wiki/BetweenAS3
ActionScript Tweener https://code.google.com/p/tweener/

Tweenアニメーションに関して各ツールではだいたい以下のものは標準化されていました。(ざっくりですみません。。)
・移動(絶対位置/相対位置)
・拡大
・回転
・Easingの指定(Quad, Elastic, Backなどの各種に関してIn, InOut, Out)

作成中はEasing早見表が便利だったので貼っておきます。
http://easings.net/ja

ちなみにiTween, BetweenAS3, cocos2d-xそれぞれの書き方が以下のようになっています
(x:100, y:100をQuadOutイージングで0.2secで移動する場合)

[iTween]

iTween.MoveTo(gameObject, iTween.Hash("x", 100, "y", 100, "time", 0.2f, "easetype", iTween.EaseType.easeOutQuad));

[BetweenAS3]

BetweenAS3.to(frog, {x:100, y:100}, 0.2f, Quad.easeOut);

[cocos2d-x]

this->runAction(EaseQuadraticActionOut::create(MoveTo::create(Point(100, 100), 0.2f));

・・・

・・・他に比べてEasingの指定方法がちょっとちがうような・・
あと同じ動きを同じ間隔、同じEasing指定で行うときになんども指定しなければならず面倒・・
そして微妙にcocos2d-xのEasing名称が長い・・

そこで!

BetweenAS3ライクなラッパー(Betweenクラス)作りました↓
https://github.com/keidroid/advent2014

こんなかきかた

this->runAction(Between::to(this, "x:100, y:100", 0.2f, Easing::QuadOut));

ラッパーなしの場合とありの場合、同時再生で回転・拡大を加えるとそれぞれ以下になります

[素で書いた場合]

this->runAction(Spawn::create(EaseQuadraticActionOut::create(MoveTo::create(Point(100, 100), 0.2f),
                              EaseQuadraticActionOut::create(RotateTo::create(30, 0.2f),
                              EaseQuadraticActionOut::create(ScaleTo::create(2.0f, 0.2f));

[ラッパーあり]

this->runAction(Between::to(this, "x:100, y:100, rot:30, scale:2", 0.2f, Easing::QuadOut));

(゚Д゚)

そもそもアニメーションをスクリプトで記述する機会は今後もあるのかよくわかりませんが
さくっとアニメーション書きたいときに合えば使ってやってください
(自分はFlashをcocos2d-xに移植するために作りました)


あしたはネイティブ連携の話!とても楽しみです!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away