Kousei Ikeda/Blog

2010.01.12/Flash

本日2010年1月12日、『Progression 4.0.1 Public Beta 1.3』がリリースされました。ぱちぱちぱち。

今回個人的にうれしい機能色々なので、勝手に紹介します。
今回は導入についてとPreloadSWFクラスについて。

導入について

注意しないといけないことというわけではありませんが僕が一瞬ひっかかった点があったので書きます。
ダウンロードしたファイル名は”Progression-ja-CS3.mxp”となっており、「あれ?CS4は?」と思われる方もいるかもしれませんが、これはCS3以上という意味なので、CS4も同じmxpで大丈夫。(とnium先生に教えてもらいました。)

追加機能 PreloadSWFクラス

LoadCommandで使用するクラスで、“PreloadSWF”というクラスが追加されました
リリースノートには以下のようにあります。

CastPreloader クラスの CastEvent.CAST_LOAD_START イベント内で、読み込まれる本体の監視処理を可能にする PreloadSWF クラスを追加しました。

これがどう便利かというと、Preloader内でIndex.swfと外部画像等を読み込む仕様の場合のロード進捗管理が大変楽になります。

とりあえず

  • Preloader.swf内でXMLを読み込む
  • それをもとに画像を読み込む
  • その画像とindex.swfとの合計を100%として進捗表示をする

という場合をサンプルとして、具体的にコードで示します。

まずPreloadSWFがない場合のコードです。

PreloadSWFがない場合のPreloader.as

package {
	import flash.net.*;
	import jp.progression.casts.*;
	import jp.progression.commands.display.*;
	import jp.progression.commands.lists.*;
	import jp.progression.commands.net.*;
	import jp.progression.commands.tweens.*;
	import jp.progression.commands.*;
	import jp.progression.data.*;
	import jp.progression.events.*;
	import jp.progression.executors.*;
	
	public class Preloader extends CastPreloader {
		
		private var _loadImageLength:Number;
		private var _myLoaderList:LoaderList;
		
		public function Preloader() 
		{			
			// プリローダーが読み込むファイルと、実行形式を指定します。
			super( new URLRequest( "index.swf" ), false, CommandExecutor );
		}
		
		override protected function atReady():void 
		{				
		}
		
		override protected function atCastLoadStart():void 
		{			
			addCommand(
				//XML読み込み
				new LoadURL(new URLRequest("assets/xml/images.xml")),
				
				function()
				{	
					//XMLから情報取得
					//今回は画像の枚数が記述してある
					var myXml:XML = new XML(this.latestData);
					_loadImageLength = myXml.images.@_loadImageLengthgth;
					
					//LoaderListを生成
					//進捗表示用にonProgressイベント設定
					_myLoaderList = new LoaderList(
						{
							onProgress:function():void 
							{								
								//index.swfも含めた進捗を出したいので、分母を1個多くパーセントを換算する
								var tmpPercent:Number = this.percent / (_loadImageLength + 1) * _loadImageLength;
								
								//進捗表示
								trace(tmpPercent);
							}
						}
					);
					
					//XMLから取得した情報をもとに画像読み込みのLoadBitmapDataコマンド生成
					//LoaderListに追加
					var n:int = _loadImageLength;
					for (var i:int = 1; i <= n; i++) 
					{
						_myLoaderList.addCommand(
							new LoadBitmapData(new URLRequest("assets/images/" + i.toString() + ".jpg"))
						);
					}
					
					//LoaderListを親であるSerialListに追加
					this.parent.addCommand(
						_myLoaderList
					);
				}
			);
		}
		
		override protected function atProgress():void 
		{
			//進捗更新
			//index.swfの進捗を、画像の枚数+index.swfで100%となるよう、割る
			var tmpPercent:Number = _loadImageLength / (_loadImageLength + 1) + bytesLoaded / bytesTotal / (_loadImageLength + 1);
			trace(tmpPercent);
		}

		override protected function atCastLoadComplete():void 
		{		
			addCommand(
			);
		}
	}
}

理系脳の人ならほんとはもっとスマートに書けそうですが、とりあえず目的は達成できます。
文系脳である僕のロジックが馬鹿すぎてみなさんが理解できない場合のために一応解説します。

①まずXMLを読み込みます。するとそこには画像枚数が書いてあります。今回は計算しやすいように仮に9枚とします。

new LoadURL(new URLRequest("assets/xml/images.xml")),

②LoaderListを生成します。

_myLoaderList = new LoaderList(

③進捗管理のためonProgressを設定します。
ここで表示されるパーセントは9枚で100%です。ですが、目的としてはindex.swfを加えたパーセントを出したいので、9枚で100%の計算でLoaderListが出してくれているパーセントを、全体がindex.swfを加えた10枚だったら何パーセントにあたるのか・・・と計算しなおします。よって画像を全部読み終わったら今回は進捗は90%まで来ます。

onProgress:function():void
{								
	var tmpPercent:Number = this.percent / (_loadImageLength + 1) * _loadImageLength;
	trace(tmpPercent);
}
);

④LoadBitmapDataコマンドを9個生成してLoaderCommandでまとめます。

var n:int = _loadImageLength;
for (var i:int = 1; i <= n; i++) 
{
	_myLoaderList.addCommand(
		new LoadBitmapData(new URLRequest("assets/images/" + i.toString() + ".jpg"))
	);
}

⑤先程のLoaderListで画像を全部読み終わると次はindex.swfの読み込みに進みます。ここではindex.swfの読み込み状況が出力されます。これは当然、index.swfひとつを読み込み終わると100%です。これを画像9枚とあわせた10枚で100%にしたいので、10で割ります。そいで90を足します。これで全体の進捗がわかります。

var tmpPercent:Number = _loadImageLength / (_loadImageLength + 1) + bytesLoaded / bytesTotal / (_loadImageLength + 1);
trace(tmpPercent);

という感じです。なんかめんどくさいですね。
これを今回追加されたPreloadSWFを使って書いてみます。

PreloadSWFがある場合のPreloader.as

package {
	import jp.progression.casts.*;
	import jp.progression.commands.display.*;
	import jp.progression.commands.lists.*;
	import jp.progression.commands.net.*;
	import jp.progression.commands.tweens.*;
	import jp.progression.commands.*;
	import jp.progression.data.*;
	import jp.progression.events.*;
	import jp.progression.executors.*;
	
	public class Preloader extends CastPreloader 
	{
		
		/**
		 * 新しい Preloader インスタンスを作成します。
		 */
		public function Preloader() 
		{			
			// プリローダーが読み込むファイルと、実行形式を指定します。
			super( new URLRequest( "index.swf" ), false, CommandExecutor );
		}
		
		/**
		 * SWF ファイルの読み込みが完了し、stage 及び loaderInfo にアクセス可能になった場合に送出されます。
		 */
		override protected function atReady():void 
		{				
		}
		
		/**
		 * オブジェクトが読み込みを開始した瞬間に送出されます。
		 * このイベント処理の実行中には、ExecutorObject を使用した非同期処理が行えます。
		 */
		override protected function atCastLoadStart():void 
		{		
			addCommand(
				//XML読み込み
				new LoadURL(new URLRequest("assets/xml/images.xml")),
				
				function()
				{			
					//LoaderList作成
					//進捗管理用にonProgress設定
					var myLoaderList:LoaderList = new LoaderList(
						{
							onProgress:function():void 
							{
								//進捗表示
								trace(this.percent);
							}
						}
					);
					
					//XMLをもとに画像読み込み用のLoadBitmapDataを生成、LoaderListに追加
					var myXml:XML = new XML(this.latestData);
					var n:int = myXml.images.@length;
					for (var i:int = 1; i <= n; i++) 
					{
						myLoaderList.addCommand(
							new LoadBitmapData(new URLRequest("assets/images/" + i.toString() + ".jpg"))
						);
					}
					
					//★
					//同じLoaderListにPreloadSWFも追加します。
					myLoaderList.addCommand(
						new PreloadSWF()
					);
					
					//画像とIndex.swfを読む込むLoaderListを親SerialListに追加
					this.parent.addCommand(
						myLoaderList
					);
				}
			);
		}
		
		/**
		 * ダウンロード処理を実行中にデータを受信したときに送出されます。
		 */
		override protected function atProgress():void 
		{				
		}
		
		/**
		 * オブジェクトが読み込みを完了した瞬間に送出されます。
		 * このイベント処理の実行中には、ExecutorObject を使用した非同期処理が行えます。
		 */
		override protected function atCastLoadComplete():void 
		{		
			addCommand(
			);
		}
	}
}

①XMLを読み込みます。

new LoadURL(new URLRequest("assets/xml/images.xml")),

②画像とindex.swfを読み込むためのLoaderListを生成します。

var myLoaderList:LoaderList = new LoaderList(
);

③進捗管理用にonProgressを設定します。先程と違い、this.percentが画像9枚+index.swf全体を100%として出力してくれるので、何も考える必要ありません。

onProgress:function():void 
{
	trace(this.percent);
}

④XMLをもとにLoaderListにLoadBitmapDataコマンドを追加していきます。

var myXml:XML = new XML(this.latestData);
var n:int = myXml.images.@length;
for (var i:int = 1; i <= n; i++) 
{
	myLoaderList.addCommand(
		new LoadBitmapData(new URLRequest("assets/images/" + i.toString() + ".jpg"))
	);
}

⑤さらに、同じLoaderListでindex.swfの進捗も管理したいので、PreloadSWFも生成して追加します。

myLoaderList.addCommand(
	new PreloadSWF()
);

という感じです。
なんと、とてもわかやすい。というか何も考えなくてよい!
Progressionがどんどん進歩して、僕の脳はどんどん退化しそうです。

まとめ

今回追加されたPreloadSWFにより、画像等外部データとindex.swfの読み込みを一つのLoaderList内ですることができ、記述や管理が非常に簡単でわかりやすくなります。
素晴らしいですね。

サンプル

一応サンプルソースを置いておきます。上記内容にTextField置いて進捗表示している程度ですが。
サンプルをダウンロード

ほかに

  • ResourcePrefecherクラス
  • Listenクラス
  • foreground、backgroundへのアクセス

あたりがいいなって思うので、追って紹介したいと思います。タイミング逃しました