Archive for the ‘ActionScript’ Category

外部SWFのシンボルを使う

SWFをいくつかにわけて、親がそれらを読み込んで、、、という作り方はよくあると思います。でもムービーの制御をすべて親SWFで行いたい場合、SWFを分ける理由は単にHTMLに貼り付けるSWFを軽くするためでしかないこともあります。

その場合、分けてしまうことでデバッグがしにくかったり、深度管理が大変だったりというデメリットが生じてしまいます。

その解決方はいくつかあるとおもいます。たとえば、
・getDefinitionByName

・getDefinition
を使う方法です。

以前にも同じような問題にその時々で解決してきたのですが、ちょっとしっくりした方法が見つかったのでメモします。

※途中割愛、はい、親ムービーで子ムービーを読み込みました。親ムービーにはchildMovieというMovieClip型のインスタンス(子ムービー)があります。

package
{
import view.Sample;//子ムービーのライブラリにあるシンボル
import flash.system.ApplicationDomain;
public class Main extends MovieClip
{
/*割愛*/
function attachSample(childMovie:MovieClip):void{
var domain:ApplicationDomain = childMovie.loaderInfo.applicationDomain;
var Sample:Class = domain.getDefinition(“Sample”) as Class;
var sample = new Sample();
addChild(sample);
}

}
}

ポイントは3つ。
・子ムービーのシンボルは1フレのどっかに張っておくか、1フレーム目に書き出しチェックボックスにチェックを入れておく。
・親ムービーにimport文を入れていつでも使える準備をしておく。
・domain.getDefinition(“view.Sample”) じゃなくてdomain.getDefinition(“Sample”)

こうすることで、デバッグ時に親ムービーに子ムービーにあるクラスが存在するかのように開発を進めることができます。

参考URL(http://www.adobe.com/jp/newsletters/edge/october2009/articles/article2/)

FlexかFlashか悩むところ

某システム案件でAIRを開発することになり、Flashを用いて開発をしていたが、これってFlexでの開発の方がいいのではないかと考え直す。
「Flash使いです」とは公言できるけど、Flexの知識は中途半端なので、得意分野を使っての開発スタートとなったわけですが、ちょっと小さめのAIRアプリケーション案件があり、それらを開発するのに「Flexでも使ってみるか」と使ってみたら意外にイイ。

というわけで、Flexをがりがりと勉強し始めると現在進行中のシステム案件も実はFlexの方が開発しやすいのではないかという結論に至ったわけです。

Flexを勉強していて一番ストレスに感じるのは、”絵がかけない”とか”動きのニュアンスちょっと違う”とかそういうところ。
美的感覚が悲鳴をあげます。でもシステムは外に見せるものではないし、そこまでビジュアル的にひどくもないし。生粋のデザイナーにはきついだろうけど、私は平気。許容範囲。
それに、慣れてくれば自由にグラフィックを調整できると思います。

そのシステム案件のスケジュールも伸びたことだし、ここはひとつFlexに舵をきってみようかと思います。

Flex勉強会もFlash勉強会もたまーに出席するけれど、出席する人がちがうんですよね。
親和性はあるはずだから、連携できればもっとすばらしい結果が出せるとおもうので残念だとは思ってました。
どちらも使える人がいれば状況は変わってくるはずなので橋渡しになれればーと思います。

ステータスを一括で管理するクラス EventDispatcher機能付

AS3の仕事が増える中、AS2で使っていたBroadcasterクラスというオリジナルクラスのようなものがほしくなり、AS3用に作りました。

まず断っておきますが、これは汎用的に使えるクラスではなくノウハウのようなものです。でも一部は汎用的に使えるコードですのでカスタマイズして使ってみると何かと重宝します。

ステータスを一括で管理するというケースではイベント処理とデータの保持の両方が必要になります。

例えば「本」のようなアプリケーションの場合、「いま何ページを表示している」といったデータはそのアプリケーションの中では一つなはずですね。でもそのデータを知りたい、もしくは変更したいオブジェクトはアプリケーションのなかで点在するものです。これをうまく解決するのにはオブザーバーパターンを使えばいいわけですが、それ自体はEventDispatcherクラスを使えば簡単に実現できます。

一方アプリケーションが中くらいの規模になってくると(例えばフルスクリーンのちょっとリッチなサイト)イベントごとにクラスを作っているとクラスだらけになってしまいます。またステータスが変わったらそれをみんなに知らせたいというケースが大半なはずですね。(ちなみにここでいうステータスとはステータスパターンとはなんの関係もありません。)

つまりオブザーバーパターンの実装とステータスの保持はセットだと話が早いというわけです。また、ステータスの種類はいくらでも増やせたほうがいいですね。

サンプルです。

  1. package
  2. {
  3. import flash.events.Event;
  4. /**
  5. * ...
  6. * @author DYO
  7. */
  8. public class MovieStatus extends Event
  9. {
  10.  
  11. //▼カスタマイズ ココカラ
  12. /*--------------------------------------------------
  13. * page
  14. --------------------------------------------------*/
  15. static public const PAGE:String = "movieStatusPage";
  16. static private var _page:int;
  17. static public function get page():int { return _page; }
  18. static public function set page(value:int):void {
  19. if(_page != value){
  20. var _value = _page;
  21. _page = value;
  22. myDispatcher.dispatchEvent(new MovieStatus({type:PAGE,current:_page,pre:_value}));
  23. }
  24. }
  25. //▲カスタマイズ ココマデ
  26.  
  27.  
  28. static private var myDispatcher:MyDispatcher;
  29. public var status:Object;
  30. public function MovieStatus(_type:Object, bubbles:Boolean = false, cancelable:Boolean = false) {
  31. var type = _type is String ? _type : _type.type;
  32. super(type, bubbles, cancelable);
  33. status = _type is String ? {current:null,pre:null,type:type} : _type;
  34. }
  35. public override function clone():Event {return new MovieStatus(type);}
  36. static public function init() {if(!myDispatcher)myDispatcher = new MyDispatcher();}
  37. static public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {myDispatcher.addEventListener(type, listener, useCapture, priority,useWeakReference);}
  38. static public function dispatchEvent(evt:Event):Boolean {return myDispatcher.dispatchEvent(evt);}
  39. static public function hasEventListener(type:String):Boolean {return myDispatcher.hasEventListener(type);}
  40. static public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {myDispatcher.removeEventListener(type, listener, useCapture);}
  41. static public function willTrigger(type:String):Boolean {return myDispatcher.willTrigger(type);}
  42. }
  43. }
  44. import flash.events.Event;
  45. import flash.events.EventDispatcher;
  46. import flash.events.IEventDispatcher;
  47. class MyDispatcher implements IEventDispatcher {
  48. private var dispatcher:EventDispatcher;
  49. public function MyDispatcher() {dispatcher = new EventDispatcher(this);}
  50. public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {dispatcher.addEventListener(type, listener, useCapture, priority);}
  51. public function dispatchEvent(evt:Event):Boolean {return dispatcher.dispatchEvent(evt);}
  52. public function hasEventListener(type:String):Boolean {return dispatcher.hasEventListener(type);}
  53. public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {dispatcher.removeEventListener(type, listener, useCapture);}
  54. public function willTrigger(type:String):Boolean {return dispatcher.willTrigger(type);}
  55. }

使うほうは
まずMovieStatusをinit()します。(これはアプリケーション内で一回でよし。ドキュメントクラスのコンストラクタでやるとベター)
つぎにファンクション定義。function onPageChanged(e:MovieStatus){trace(e.status.current);}
最後にイベント登録。MovieStatus.addEventListener(MovieStatus.PAGE,onPageChanged);

あとはMovieStatus.page = 1;とかすると先ほどのonPageChangedが呼ばれます。

今回はpageというステータスを用意しましたが、サンプルの「カスタマイズ」の部分を増やしたり改造したりすることで、アプリケーションごとに設定することができます。

本当は最初にinitするという仕様が腑に落ちないのですが、staticなクラスにしたかったことと、一つのクラスにまとめたかったことと、singletonなんかつかっていちいちインスタンス化するのが面倒だったことがあってこうなりました。ベターな方法があれば教えてください。