kojiko-android’s blog

開発中にハマった時の解決策や、忘れがちなことを残しておきます。

アニメーションさせる(Canvasを使ったゲームなど)

 パズルゲームなどで、タイルを動かした時に、瞬時に移動するのではなく、
滑らかにアニメーションしながら移動したい。
 なおかつ、端末の処理速度などによって、早くなったり遅くなったりせず、どのような端末でも一貫した動きが欲しい。

 そのような機能を求めるときは、ValueAnimator が、汎用性も高く便利です。


ValueAnimatorの使い方の流れです。
ValueAnimator animator = ValueAnimator.ofFloat(0.0f,1.0f);

animator.setDuration(1000l);

animator.setInterpolator(new AccelerateInterpolator());

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

               float value = (float)animation.getAnimatedValue();

                invalidate();

            }
        });

animator.start();


ValueAnimatorをインスタンス化します。
パラメーターで、初期値と、変化後の値を設定します。

例では、float型で、0.0から1.0まで変化するアニメーションです。

setDuration(1000l)は、何ミリ秒間かけて変化させるか、を設定します。lは、long値であることを明確にしています。

setInterpolator(new AccelerateInterpolator())は、変化の仕方のバリエーションを指定します。
コードから記述するときは、このように匿名クラスを引数にしています。
AccelerateInterpolatorは、徐々に加速していくアニメーションです。
インターポレーターには、引っ張って離すようなものや、終着点でバウンドするものなど、様々な種類があります。


他にも、ディレイをかけたり、繰り返しを指定するメソッドがあります。


start()を呼び出すとアニメーションが開始されますが、
内部的に数値が変化しているだけで、見た目には何も変わりません。
変化した値を取得し、パズルのタイルの位置や、飛んでいる玉の座標に適用する必要があります。

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                
                float value = (float)animation.getAnimatedValue();

        //    valueを使って何かをする

                invalidate();

            }
        });


値が変化するたびに呼び出されるリスナーをセットします。

float value = (float)animation.getAnimatedValue();

で、値を取得します。今回はfloat型のアニメーションを定義したので、float型にキャストします。
ここで得られた値を、動かしたい対象の座標などに適用して、

invalidate()で、onDrawを発生させます。
先ほどの値のぶんだけ動いたアニメーションが実現されます。

start()を、最後に忘れないで下さいね。


注意すべきことは、0.0から1.0までの間の、全ての値が順番に呼び出されるわけではありません。
例えば、0から360の整数値で変化するアニメーションの場合、180を踏まないこともある、ということです。

アニメーションの終了を検知
    animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                
                
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animator.start();

アニメーションの各ポイントで呼び出されます。

パズルのタイルが動いている間は、タップを受け付けない、など、
アニメーションが一通り終わるのを待たせたいとき等に便利です。

このリスナーを登録するときは、start()の前に行うことにご注意ください。



 ValueAnimatorは、ユーザーの操作のレスポンスにも向いているので、
そこまでリアルタイム性のないゲームではかなり重宝されると思います。
とくに0.0fから1.0fへの変化のアニメーションは、とても汎用性があります。
色を変化させるアニメーションもあります。
変化量を自力で計算するのは非常に大変なので、活用の場は多そうです。


 最後に宣伝っぽくなってしまいますが、
このValueAnimatorをふんだんに使ったシンプルなパズルゲームを作りました。
動き一つひとつに補間のモーションが付与されることによる視覚的な効果を実感いただけると思いますので、
よかったらチェックしてみてください!
play.google.com

f:id:kentaro198477:20160520093118p:plainf:id:kentaro198477:20160520093112p:plain