‘AS3’ タグのついている投稿

Progression4でコンポーネントスタイルとクラススタイルを行き来する

2010 年 5 月 20 日 木曜日 正宗

先日書きました、Progressionのコンポーネントとクラスを混在させるやり方の記事を、コンポーネントスタイルからの視点で書きました。いちおうProgressionのコンポーネントでの作成スタイルを一回でもやった方を対象に書いています。もしまだProgressionのコンポーネントスタイルを試されてない方は最初はそっちをやってみないと意味が分からないと思うし、このスタイルが何故必要なのかもわかりにくいかと思います。
それでも一般に誤解されているようにコンポーネントは初心者だけがやるものではなく、こういった工夫一つで非常に表現力の高いサイトを作ることもできるので、ぜひ参考にしてもらってみなさんのProgressonライフに役立てば幸いです。

(続きを読む...)

Progression4:SceneObjectでシーンの構造管理はしない

2010 年 5 月 15 日 土曜日 正宗

みなさんはもう手に入れましたか?ProgressionによるFlashコンテンツ開発ガイドブック
なんでも発売から二週間足らずで重版決定だそうで。おめでとうございます!

僕はと言うと、先週行われたProgression本を朗読する会に参加してきました。せっかく買った本なんだから読まなきゃね!
で、この朗読会、スーパー肩パッドさんとシナチクさんがTwitterで音頭をとって開催された企画でして、非常に面白くてためになりました。

まず14時から開始して19時半まで5時間半、ぶっとおしでProgression談義。その後居酒屋に移動して3時間またぶっとおしでFlash談義。
僕自身も大阪てら子でProgressionを勉強したのが2年前。出会って以来この2年間で覚えてるだけで15案件、実際には20案件以上は実践投入してきたほどハマりまくってるProgressionについて、ここまでディープに語り合える場と仲間がいなかったので(個人事業なので家内以外仕事のパートナーが居ないので孤独)ここまで時間を忘れて、ほぼ初対面の方々たちと語らいだのは生まれて初めての経験でした。

本当にいい刺激になりました。

で、いちおう自分がとってたノートもあるんだけど、皆さんの喋った内容がまとめきれていないので、せめて自分のネタだけでもまとめておこうと思ったわけです。

21日の僕の勉強会でもこれやります。
不思議なことに全く同じ記事を「クラススタイル向け」と「コンポーネント向け」で2回書きます。今回はその第一回目です。
第一回目は、「クラススタイル向け」に書いてみようと思います。

(続きを読む...)

5/21(金) Progressionお勉強会やります

2010 年 4 月 27 日 火曜日 正宗

Progressionお勉強会 UTWEB5/21にProgressionの勉強会をやります-!

詳しい内容はこちらのリンクを参照して下さい。

以前も何度かProgressionのコンポーネントとクラスの話題はこのブログでもやってきていますが、いろいろと情報も古くなってきてたり微妙に間違えているところがあったりしてたので、Progression4も正式公開したことだしここいらへんで情報共有の良い機会ではないかと思ったわけです。

(続きを読む...)

ActionScriptイベントリスナの外にある変数を使いたい

2010 年 2 月 11 日 木曜日 正宗

すいません。wonferfl本まだ買っていません。今すぐ読みたい!正宗です。
今回は僕がいつも忘れてしまうことを備忘録がわりに書いておきます。
(続きを読む...)

Progression3でクラススタイルにコンポーネントを連携させる(1/3)

2009 年 12 月 2 日 水曜日 正宗

世間はProgression4の話題でもちきりですが、いまだProgression3の話題を書こうとしている流行にうとい男、正宗です。
以前紹介した「Progressionでコンポーネントスタイルにクラスを連携させる」の続きです。
今回から進めて全3回の予定でやってみます。

以前紹介したやり方は「まずコンポーネントスタイルで作ってみて、ちょっとずつクラスを混ぜ込んでみよう」というものでしたが、今回からは「いかにスクリプトを書かずにすむようにスクリプトを書くか」です。

一見、矛盾してそうなコンセプトですが、前回よりも研究結果がだいぶ洗練されてきたので、スクリプトアレルギーの方も、よりコピペだけでまともに動かせるようにはなっていったかなと思います(^^;
(続きを読む...)

CSS Nite in OSAKA, Vol.16サンプル、スライド置き場

2009 年 6 月 9 日 火曜日 正宗

CSS Nite in OSAKA, Vol.16に使用したサンプルとスライドです。

こちらからダウンロードして下さい。

CSS_Nite_OSAKA_vol16_masamune_sample.zip

サンプルはご本人の学習目的での使用においてご自由に使って頂いて結構ですが、むやみな転載や再配布はお控え下さい。

CSS Nite in OSAKA, Vol.16補足ツボ

2009 年 6 月 9 日 火曜日 正宗

皆様、CSS Nite in OSAKA, Vol.16 「これから始めるFlashActionScriptツボのツボ」にお越し頂きありがとうございました。ActionScriptをこれから始めてみようというきっかけになれば幸いです。

セミナーでは「とにかくこう書いてみれば動くので始めてみるきっかけになれば」という部分のみに焦点を当てて紹介しておりますので、なるべくかみ砕いて幾つかの部分であえて簡略的な表現をこころがけています。
はじめて触るぶんには必要としないであろう知識ですが、これから本格的に学習される方に向けて出来るだけ詳細な情報を補足という形でここにまとめさせていただきます。
(続きを読む...)

ProgressionのCommandが良い感じ

2009 年 5 月 21 日 木曜日 正宗

こんにちは。
正宗です。
今日はProgressionのCommandのお話をしたいと思います。
毎度ながら僕個人の備忘録となっているので、誰も役に立たない情報ですが僕が便利だと感じるならそれでいいんです。

Flashサイト制作の上でもはや手放せないフレームワーク、その名も「Progression
Scene管理も秀逸ですが僕がProgressionを使ってて何よりも惚れ惚れするのがCommandがよく練られていてとっても使いやすいところなのです。
「こういうこともCommandで出来ないかな?」とリファレンスを読み読みしてると必ず上手いやり方が用意されていて、どんどん使っていくうちにいわゆる「Progression的な」コードの書き方に身が染まっていって毎日新しい発見があってコードを書くのがとても楽しいです。
(もちろん、Progression的な書き方を強制されるわけでは無くって、我流の書き方も完全に許容されているところもこのフレームワークを好きな理由の一つです)
ということで、今まで勉強してきたCommandの使い方の途中段階までをまとめておきたいと思います。

基本のキホン

まずCommandがどこで実行されるかですが、一番簡単なのは
SceneObjectでしたら_onLoad、_onInit、_onGoto、_onUnloadの関数の中に直接addCommandしておく方法。
CastSpriteやCastMovieClipなどは_onCastAddedや_onCastRemovedなんかに直接addCommandしておきます。
このへんのシーン管理やイベント管理もとっても面白いんでいろいろとまとめたいところなんですが、今日のまとめはあくまでCommandだけにとどめておきたいと思います。

SerialListとParallelList

  • SerialListは順番にコマンドを実行する
  • ParallelListは一度に同時にコマンドを実行する
  • SerialListに配列としてコマンドをaddCommandすればその配列内のコマンドはParallelListとして実行される
  • 逆にParallelListに配列としてコマンドをaddCommandすればその配列内のコマンドはSerialListとして実行される
  • _onInitなんかの関数の中は最初はSerialList

こんなところでしょうか。
使い方はこんな感じ。

 
private function test():void {
	var list:SerialList = new SerialList();
	list.addCommand(
		new LoadURL(new URLRequest("hoge.xml")),//XMLの読み込みを開始
		function():void {
			trace(new XML(this.latestData));//読み込んだXMLを出力
		},
		[
			new DoTweener(front, { alpha:0, time:1 } ),//前面のMCを1秒かけて透明に
			new DoTweener(back, { alpha:1, time:1 } )//背面のMCも同時に1秒かけて不透明に
		]
	);
	list.execute();//SerialListを実行
}
 

最初にSerialListで実行させているので、XMLの読み込みを待って完了したら自動的に次の処理に移ります。
その後配列で登録してあるのでクロスフェードの処理はParallelListとして同時に実行されることになります。
そうめんもそうなんですが、もうaddEventListenerだらけで「えっと、ここが完了したら次こうなって…」と悩まされなくて済むようになりました。

外部swfのクラスを使いたい

こんだけイケてるCommandなのですから、シーンの読み込みの際に外部swfを取得してそこからクラスを参照するやり方も何か用意されているのではないかと思って調べてたら、やっぱりありました。
LoadObjectといって、CastLoaderを監視するコマンドがありました。
さすがtaka:nium先生!もう俺は一生Progressionについていくぜー!

 
package
{
	import flash.display.Sprite;
	import jp.progression.casts.*;
	import jp.progression.commands.*;
	import jp.progression.commands.display.LoadObject;
	import jp.progression.events.*;
	import jp.progression.loader.*;
	import jp.progression.*;
	import jp.progression.scenes.*;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.ApplicationDomain;
	public class Test extends CastSprite
	{
		private var _loader:CastLoader;
		private var _context:LoaderContext;
		public function Test( initObject:Object = null )
		{
			super( initObject );
			_loader = new CastLoader();
			_context = new LoaderContext();
			_context.applicationDomain = ApplicationDomain.currentDomain;
		}
		protected override function _onCastAdded():void
		{
			addCommand(
				new DoTweener(this, { alpha:0 } ),
				new LoadObject(_loader, new URLRequest("hoge.swf"), {
					context:_context,
					onCastLoadComplete:function():void {
						var myDomain:ApplicationDomain = _loader.contentLoaderInfo.applicationDomain;
						var myClass:Class = _myDomain.getDefinition("onigiri") as Class;
						var mc:Sprite = new myClass();
						addChild(mc);
					}
				}),
				new DoTweener(this, { alpha:1, time:1 } )
			);
		}
	}
}
 

実際にはLoadObjectのonCastLoadCompleteに登録しなくっても、そのままシリアルリストに次の処理を書いていってもよさげ。

だけどここで少しばかり問題が。
上に挙げたサンプルはCastなにがしで処理を行っているので問題ないんだけれど、SceneObjectでこれをやろうとするとCommandの参照の問題が出てくるような気がする。

例えばある特定のScene以下からは"hoge.swf"を読み込んでその階層以下からのSceneでは"hoge.swf"を使い回したい場合

 
package
{
	import jp.progression.casts.*;
	import jp.progression.commands.*;
	import jp.progression.events.*;
	import jp.progression.loader.*;
	import jp.progression.*;
	import jp.progression.scenes.*;
	import jp.progression.commands.display.LoadObject;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.ApplicationDomain;
	import HogePage;
 
	public class HogeScene extends SceneObject
	{
		private var _page:HogePage;
		private var _singleton:Singleton;
		private var _loader:CastLoader;
		private var _context:LoaderContext;
 
		public function HogeScene( name:String = null, initObject:Object = null ) {
			super( name, initObject );
 
			title = "hogehogeシーン";
 
			_loader = new CastLoader();
			_context = new LoaderContext();
			_context.applicationDomain = ApplicationDomain.currentDomain;
 
		}
 
		private function init():void {
			var myDomain:ApplicationDomain = _loader.contentLoaderInfo.applicationDomain;
			_page = new HogePage(myDomain);
 
			removeAllScenes();
			var fugaHelp:DressHelpScene = new fugaHelpScene(myDomain);
			fugaHelp.name = "help";
			addScene(fugaHelp);
		}
 
		protected override function _onLoad():void
		{
			addCommand(
				new LoadObject(_loader, new URLRequest("dressshop.swf"), {
					context:_context
				}),
				init,
				new AddChild(progression.container, _page)
			);
		}
 
		protected override function _onInit():void
		{
			addCommand(
			);
		}
 
		protected override function _onGoto():void
		{
			addCommand(
			);
		}
 
		protected override function _onUnload():void
		{
			addCommand(
				new RemoveChild(progression.container, _page),
				function():void {
					_loader.unload();
				}
			);
		}
	}
}
 

こんなふうに書くと動かなくなる。
何故これがだめなのかは

 
package
{
	import jp.progression.casts.*;
	import jp.progression.commands.*;
	import jp.progression.events.*;
	import jp.progression.loader.*;
	import jp.progression.*;
	import jp.progression.scenes.*;
	import jp.progression.commands.display.LoadObject;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.ApplicationDomain;
	import HogePage;
 
	public class HogeScene extends SceneObject
	{
		private var _page:HogePage;
		private var _singleton:Singleton;
		private var _loader:CastLoader;
		private var _context:LoaderContext;
 
		public function HogeScene( name:String = null, initObject:Object = null ) {
			super( name, initObject );
 
			title = "hogehogeシーン";
 
			_loader = new CastLoader();
			_context = new LoaderContext();
			_context.applicationDomain = ApplicationDomain.currentDomain;
 
		}
 
		private function init():void {
			var myDomain:ApplicationDomain = _loader.contentLoaderInfo.applicationDomain;
			_page = new HogePage(myDomain);
 
			removeAllScenes();
			var fugaHelp:DressHelpScene = new fugaHelpScene(myDomain);
			fugaHelp.name = "help";
			addScene(fugaHelp);
 
			trace(this, _page);
		}
 
		protected override function _onLoad():void
		{
			addCommand(
				new LoadObject(_loader, new URLRequest("dressshop.swf"), {
					context:_context
				}),
				init,
				new Trace(this),
				new Trace(_page),
				new AddChild(progression.container, _page)
			);
		}
 
		protected override function _onInit():void
		{
			addCommand(
			);
		}
 
		protected override function _onGoto():void
		{
			addCommand(
			);
		}
 
		protected override function _onUnload():void
		{
			addCommand(
				new RemoveChild(progression.container, _page),
				function():void {
					_loader.unload();
				}
			);
		}
	}
}
 

こう書いてみるとなんとなくわかるんだけれど、じゃあどうすればいいかというと僕はこうしました。

 
package
{
	import jp.progression.casts.*;
	import jp.progression.commands.*;
	import jp.progression.events.*;
	import jp.progression.loader.*;
	import jp.progression.*;
	import jp.progression.scenes.*;
	import jp.progression.commands.display.LoadObject;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.ApplicationDomain;
	import HogePage;
 
	public class HogeScene extends SceneObject
	{
		private var _page:HogePage;
		private var _singleton:Singleton;
		private var _loader:CastLoader;
		private var _context:LoaderContext;
 
		public function HogeScene( name:String = null, initObject:Object = null ) {
			super( name, initObject );
 
			title = "hogehogeシーン";
 
			_loader = new CastLoader();
			_context = new LoaderContext();
			_context.applicationDomain = ApplicationDomain.currentDomain;
 
			_page = new HogePage(myDomain);
		}
 
		private function init():void {
			var myDomain:ApplicationDomain = _loader.contentLoaderInfo.applicationDomain;
			//_page = new HogePage(myDomain);
			_page.myDomain;
 
			removeAllScenes();
			var fugaHelp:DressHelpScene = new fugaHelpScene(myDomain);
			fugaHelp.name = "help";
			addScene(fugaHelp);
 
			trace(this, _page);
		}
 
		protected override function _onLoad():void
		{
			addCommand(
				new LoadObject(_loader, new URLRequest("dressshop.swf"), {
					context:_context
				}),
				init,
				new Trace(this),
				new Trace(_page),
				new AddChild(progression.container, _page)
			);
		}
 
		protected override function _onInit():void
		{
			addCommand(
			);
		}
 
		protected override function _onGoto():void
		{
			addCommand(
			);
		}
 
		protected override function _onUnload():void
		{
			addCommand(
				new RemoveChild(progression.container, _page),
				function():void {
					_loader.unload();
				}
			);
		}
	}
	public class HogePage extends CastSprite
	{
		private var _myDomain:ApplicationDomain;
		public function set myDomain(value:ApplicationDomain):void
		{
			_myDomain = value;
		}
	}
}
 

他にもどうしても_onLoadのときに動的にクラスを生成しなければならなかったりした場合はもうちょっと違う書き方をするんだけど、僕の書いたどれもが根本的にCommandで処理できる流れになってなくて、ものすごい気持ち悪いです。
ひとえに僕がCommand内のthisの参照をよくわかっていないからだとは思いますが、もうちょっとCmmandだけで完結できる方法を勉強してみたいと思います。
目指せ!ProgressionのCommandマスター!

URLRequestでキャッシュさせない方法

2009 年 5 月 6 日 水曜日 正宗

こんにちは。正宗です。
今日はURLRequestのキャッシュの話をしたいと思います。

よくURLLoaderクラスなんかでキャッシュをさせない方法としてURLRequestのURLの末尾にランダムな数字を入れるという方法が紹介されています。
こんなやつ

 
new URLRequest("http://exsample.com/?rnd=" + int(Math.random() * 1000));
 

バナーとかサイトトラッキングなんかのクエリ発行でもよく使われていますね。

これは、通常キャッシュはURLをそのままファイル名として保存しているため、アクセスする際に毎回末尾にランダムな数字をパラメーターとして与えることで、キャッシュファイルを別々のファイルとして保存させておくことで有効な方法ですが、少しだけ不安が残ります。

それはキャッシュ対策として int(Math.random() * 1000)などの0~999などの整数値を使用した場合、1000回に1回は同じ数字を生成する可能性があるので、そのときにキャッシュを拾ってきてしまうんじゃないかという不安です。
整数じゃなくてそのままMath.random()とすることも出来ますが、結局同じ数字を生成する可能性をコントロールできていない以上根本的な解決になっていないかもしれません。

URLRequestHeaderでpragma:no-cacheを指定するという方法もありますが、IEなんかでどうもキャッシュしてしまったりで、こちらもなかなか使いづらいものとなっています。
(何より実験でRSSリーダーなんかをチャチャッと作るときとか面倒臭いし…)

そこで僕がいつも使っているキャッシュをさせない方法を紹介したいと思います。

 
new URLRequest("http://exsample.com/?rnd=" + (new Date).time);
 

これだと、末尾の数値に1970 年 1 月 1 日 0 時のミリ秒が付加されますので、1000分の一秒以内に2回以上アクセスを行わない限りはキャッシュを読み込まないことになります。

キャッシュさせない方法としてランダムな数字を使うより時間の数値を使う方が有効なのは、結構簡単なことですがあんまり紹介されてないので、よかったら参考にしてみて下さい。

WEB3D

2009 年 4 月 23 日 木曜日 正宗

ちょうど同じ期間でPaperVisionのWEB3D案件とFlashPlayer10を使ってのWEB3D案件を二つこなしたので、それを通じて僕が感じたそれぞれの一長一短を覚え書きしておきます。
(続きを読む...)