@nifty 年賀状 2010
2009 年 11月 20 日 金曜日 kosuke@nifty 年賀状 2010 用にオリジナル年賀状素材を7点作りました。
といっても作ったのは僕じゃありませんが。Yさんのお仕事。
@nifty 年賀状 2010には多数年賀状素材が揃ってます。
年賀状をお探しの際は是非ご覧ください。
@nifty 年賀状 2010 用 オリジナル年賀状素材
http://nenga.nifty.com/
Producer / 株式会社グッドファーム・プランニング
Design&Illustration / Yoco,Nakamura.nipx
Proxyクラスのこと
2009 年 11月 9 日 月曜日 kosukeProxyクラスはどんな時使うものか見当のつかない状態だったのだけど、便利に使えそうなケースが見つかったのでエントリー。
Proxyについてはここに説明がある。
ActionScript 3.0 言語およびコンポーネントリファレンス
これ読んでも正直なんのこっちゃって思っていた。
思いついた方法は、複数のオブジェクトのいくつかのプロパティを一斉に変更したい時、Proxyを介して変更するってもの。いろんな方法があると思いますが、Proxyを介して行うのもなかなか便利そうです。
以下のように複数の表示オブジェクトがあり、それらのプロパティを変更したいとします。
まず、表示オブジェクトを配列なりVectorなりに格納する。
var vector:Vector.<MovieClip> = new Vector.<MovieClip>(); vector.push( this.arrow0 ); vector.push( this.arrow1 ); vector.push( this.arrow2 ); vector.push( this.arrow3 ); |
これをProxyを継承したクラスに渡す。
this.proxy = new ProxyMcGroup( vector ); |
Proxyを継承したクラスではVectorを変数に代入する。
継承する時はdynamicで宣言しておいた方が、proxy.xのようにドットシンタックスでプロパティを参照してもエラーにならないのでいいと思う。
public dynamic class ProxyMcGroup extends Proxy{ private var _item:Vector.<MovieClip>; public function ProxyMcGroup( _item:Vector.<MovieClip> ){ super(); this._item = _item; } } |
Proxyを継承したクラスのsetPropertyをオーバーライトし、Vectorを繰り返し処理でプロパティを変更する。
override flash_proxy function setProperty(name:*, value:*):void{ for each( var i:MovieClip in this._item ){ i[name] = value; } } |
ひとまずこれだけで、複数オブジェクトのプロパティを一斉に変更できるようになる。
複数オブジェクトが同じプロパティを持つことを前提に、どのプロパティも変更できる(これが便利なポイント)はずです。
このままだと、setterだけなので取得が出来ない。
また例えばTweenerで動かす時はTweenerがhasOwnPropertyを使ってプロパティの有無を確認したりするので、必要に応じて拡張していく。
サンプルのは以下のようプロパティ値をDictionaryに保存するようにしたり、for…inステートメントでプロパティの参照が出来るようにしてみた。
package{ import __AS3__.vec.Vector; import flash.display.MovieClip; import flash.utils.Proxy; import flash.utils.flash_proxy; import flash.utils.Dictionary; public dynamic class ProxyMcGroup extends Proxy{ private var _item:Vector.<MovieClip>; private var _dictionary:Dictionary; private var _prop:Array; public function ProxyMcGroup( _item:Vector.<MovieClip> ){ super(); this._item = _item; this._dictionary = new Dictionary(true); this._prop = []; } override flash_proxy function callProperty(methodName:*, ...args):*{ trace( "callProperty:" + methodName + "," + args ); return; } override flash_proxy function getProperty(name:*):*{ trace( "getProperty:" + name ); return this._dictionary[name]; } override flash_proxy function setProperty(name:*, value:*):void{ trace( "setProperty:" + name + "," + value ); if( !this._dictionary.hasOwnProperty(name) ){ this._prop.push( name ); } this._dictionary[name] = value; for each( var i:MovieClip in this._item ){ i[name] = value; } } override flash_proxy function hasProperty(name:*):Boolean{ trace( "hasProperty:" + name ); return this._dictionary.hasOwnProperty(name); } override flash_proxy function deleteProperty(name:*):Boolean{ trace( "deleteProperty:" + name ) this._prop = this._prop.filter( function( item:*, index:int, array:Array ):Boolean{ if( item == name ) return false; else return true; } ); return delete _dictionary[name]; } override flash_proxy function getDescendants(name:*):*{ return; } override flash_proxy function nextNameIndex(index:int):int{ trace( "nextNameIndex:" + index ); if( index < this._prop.length){ return index + 1; } else{ return 0; } } override flash_proxy function nextName(index:int):String{ trace("nextName:" + index); return this._prop[index - 1]; } override flash_proxy function nextValue(index:int):*{ trace("nextValue:" + index); return this._dictionary[ this._prop[index - 1] ]; } } } |
動かしているところはProgressionのSerialListを使っています。
動かす前に使うプロパティに値を入れておく。
this.proxy.rotation = 0; this.proxy.alpha = 1; this.proxy.scaleX = 1; this.proxy.scaleY = 1; var comm:SerialList = new SerialList( { onComplete:function():void{ this.execute(); } }, new DoTweener( this.proxy, { rotation:360, transition:"easeInOutExpo", time:2 } ), new DoTweener( this.proxy, { alpha:0.5, transition:"easeNone", time:1 } ), new DoTweener( this.proxy, { scaleX:1, scaleY:1, _bezier:{ scaleX:0, scaleY:0 }, transition:"easeInOutExpo", time:1 } ), new DoTweener( this.proxy, { rotation:0, transition:"easeInOutExpo", time:2 } ), new DoTweener( this.proxy, { alpha:1, transition:"easeNone", time:1 } ) ); comm.execute(); |
ProxyはTweensy FXの時に久しく出てきて今回の使い方を気づいた。
思いもよらないところでつながることは良くある。何かを調べるってことは良いことだ。
インバースキネマティックを試す
2009 年 11月 6 日 金曜日 kosukeFlash CS4で目玉機能の一つでありながら、なんとなく影が薄いインバースキネマティック。
その理由か否か試してみてわかったことで、スクリプトからはちょっと使いづらいなぁと思った。
試してみたのはこちら。なんだか夢に出てきそうな気持ち悪さ。
rotation関連のスライダーは花の幹の部分の全ジョイントを変更。
IKMoverは花のアイコンを動かしています。
まず、インバースキネマティックの構造定義をアーマチュアといい、シンボルをつなぐ場合、表示オブジェクトが骨(ボーン)でつながった構造になります。ちなみにシェイプにボーンを通すことも出来る。
▲オーサリングツールで設定
アーマチェアはIKArmatureクラスで定義されるのだけど、これがスクリプトでは作れない。
Flashのオーサリングツールからしか作れないということ。
つまり、new IKArmature()とかして、スクリプトから表示オブジェクトをボーンでつないでいくことは出来ません。定義されたアーマチェアの構造を変更するのも無理。たとえばスクリプトでボーンを追加するとかも出来ない。
じゃあ、スクリプトで何が出来るかっていうとオーサリングツールで設定できるプロパティの変更とボーンの接続部(ジョイント)を移動させるとかです。
たとえば今回使った回転関連のプロパティは以下のように対応しています。
蛇足ですが、上のキャプチャで最小の-45°のところ、スクリプトで取得するとラジアンになって返ってくる。でもスクリプトで設定するときは角度。うーん…。
普通の使用方法ならスクリプトですることも大抵はポーズの変更をすることかと思う。
そうなるとポーズを作るのに単純なアニメーションはスクリプトでもと思いますが、いわゆる機械的じゃないアニメーションというか…規則的でないアニメーションはタイムラインで作り込んでいく方が効率いいってなるんだよなぁ。何か工夫を考えたい。