【openFrameworks】ofxTweenでアニメーションさせる【ofxTween】
こんばんは.1000chです. 関数型のパラダイムを知りたいなーと思いClojureの勉強を始めました. まだ基本文法を知っただけですが,昔嫌いだったカッコの嵐も今はそこまで抵抗無く読めて成長を感じています.
まだ今は,ね.
さて今日もoFネタでいきますよ.
oFでアニメーション
「oFでアニメーション?updateで値を動かすだけじゃん?」
はい,その通りです.シンプルなアニメーションであればそれでokです.
しかし「徐々にゆっくり」とか「最初はゆっくり,最後は急激に」とかの変化を作ろうとすると,以外と式の設計が面倒だったりします. いわゆるイージングというやつですね(イージングについては以下参照).
イージングの仕組み - イージングとはなにか | CodeGrid
また「ある値まで行ったらストップ」とか「複数の値変化の開始,終了同期を取る」とかやろうとすると,途端にコードが煩雑になります. 前者はフラグ管理変数がどんどん増えていき,後者はそれぞれのdiff値を計算し保持しておく必要が出てきます. 「タップされたときだけ,ちょっと動いてほしい」とかはよくある話ですよね.
いずれにせよ,ofAppクラスの中にメインロジックでない要素が増えてくることは請け合いです.
ofxTween
そこで利用したいのがこのアドオン,ofxTweenです.
このアドオンは,
- 十数種類用意されたeasing functionに沿って値を変化させられる
- duration, delayの設定が簡単
- 複数値のsyncした変化もお手の物
という,ちょっとしたアニメーションを付ける際になかなか便利なアドオンになってます. oF公式のaddon紹介の中でも,star的に見ても人気の高いアドオンです.
というわけで今回は,このofxTweenwつかったアニメーションの作り方を見ていきます.
使い方
公式ページからzip DLするなり,git clone
するなりしてアドオンを入手し,oFのアドオンディレクトリ内に配置してください.
この状態でproject generatorから,ofxTweenを含んだ新しいプロジェクトを作成しましょう. アドオン追加についての情報はこちらが詳しいです.
openFrameworks Addonを使用する | yoppa org
ofxTweenの利用は,以下のステップで行います.
- ofxTweenインスタンスをつくる
- 作成したインスタンスに,「tween終了時のコールバックid・イージングの方法・初期値・終了値・持続時間(ms)・待機時間(ms)」を指定する.
- updateメソッドで値を更新する
- 必要に応じてtweenされた値を取得し,描画ロジックで利用する
たったのこれだけ!
ぶっちゃけ1つめはヘッダ定義で終了.3つめはofApp::update
内でtwn.update
を呼ぶだけ.
実質ロジック部になっているのは2つめだけですが,これもtwn.setParameters
メソッドを呼ぶだけなのでかなりお手軽です.
では,実際にコードでみてみましょう. 起動から1000[ms]後に1000[ms]かけて移動するサンプルプログラムです.
// ofApp.h #pragma once #include "ofMain.h" #include "ofxTween.h" // add class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); // add from here ofxTween twn; ofxEasingBounce easing_bounce; }; // ofApp.cpp #include "ofApp.h" //-------------------------------------------------------------- void ofApp::setup(){ twn.setParameters(1,easing_bounce, ofxTween::easeOut, 100, ofGetWidth()-100, 1000, 1000); } //-------------------------------------------------------------- void ofApp::update(){ twn.update(); } //-------------------------------------------------------------- void ofApp::draw(){ ofCircle(twn.getTarget(0), ofGetHeight()/2, 50); // updateはindex0の値を返すので,こうもかける // この場合update()内にはなにも記述しなくてok // ofCircle(twn.update(), ofGetHeight()/2, 50); } // 以下略
実行結果
なんと,これだけでバウンドするエフェクトを作れてしまいました!簡単ですねー.
setParemeter
で初期化してupdate
で時間が進む.この手順をおぼえてしまえばofxTweenは8割方マスターと言えるでしょう.
update
を呼ぶかどうかのフラグを作れば,一時停止も簡単に実装できそうですね.
ここですこしsetParameter
メソッドを詳しく見てみましょう.
ofxTween内の定義をのぞいてみます.
// ofxTween.h void setParameters( int _id, ofxEasing & _easing, ofxEasingType _type, float _from, float _to, unsigned _duration, unsigned _delay);
上から見ていくと.
- id : コールバック関数に引数としてわたるID.どのtweenかを識別する為のもの.自分の自由につけてok.
- easing : ofxEasingクラスのインスタンスを渡す.様々なイージング方法がofxEasingの派生クラスとして定義されている.
- type : easeIn, easeOut, easeInOut の3つから選択(後述).
- _from : 初期値
- _to : 終了値
- _dutration : 何[ms]かけて変化するか
- _delay : 何[ms]後にtween開始するか
という感じです.
easeIn, easeOut, easeInOutの違いはこんな感じ.
上からeaseIn,easeOut,easeInOutです. このへんは先程紹介したeasing function早見表が参考になるでしょう. bounceの例は右下に載ってますね.
なお,複数の値を同じeasing,duration,delayで扱いたいのだけど,という時には,ofxTweenインスタンスを変数分用意すること無く,
一つで賄うことが出来ます.その場合,各値は追加した順にgetPosition(int pos)
メソッドで取得できます.
twn_multi.setParameters(easing_bounce, ofxTween::easeIn, 100, ofGetWidth()-100, duration, delay); //twn_multi.getPosition(0)で取得可 twn_multi.addValue(500, 100); //twn_multi.getPosition(1)で取得可 twn_multi.addValue(300, 1000); //twn_multi.getPosition(2)で取得可
一つのtweenをもとに自前で計算することももちろんできますが,便利なのでおぼえておくと良いテクニックかもしれないです.
また,各tweenは一度_toの値まで行くと変化しなくなりますが,再びsetParameter
を呼ぶことで何度でも利用可能です.
例えば先の例ですと
void ofApp::mousePressed(int x, int y, int button){ twn.setParameters(1,easing_bounce, ofxTween::easeOut, 100, ofGetWidth()-100, 1000, 1000); }
とすることでクリックするたびにtweenイベントが初期化されます. こちらも頭の片隅に置いておくと,柔軟なtweenアニメーションが作成できるでしょう.
まとめ
触った感想としては,シンプルに値を変化させる際には使いやすいなーと思いました.
しかし,デフォルトではTween.js
にあるようなメソッドチェーン的な利用するには少し工夫が必要です.
あまりスマートな方法では無いのですが,次回はそちらをご紹介できればと思います.