プリローダー1 AS3 Project with Preloader

2010.11.15kickbaseActionScript3.0 | FlashDevelop


今回はFlashDevelop(以下FDと省略)を使ってプリローダー付きのコンテンツを作成する方法について解説します。Flash IDEで言えば古くからある手法で、1フレーム目にプリローダーを設置し、2フレーム目にコンテンツを作成。root全体をロード完了するまで1フレームで止めておいて・・・という処理を行ったことがある方も多いことと思います。

本ブログではクラスベースの開発をメインに据えているので、上記の方法を丸ごとクラスで置き換えてみましょう。FDには便利なテンプレートがあるので、意外と簡単です。チューニングについては次回お話するので、今回はまず構造と簡単な実装を行ってみましょう。

※リファレンスのため、最低限の機能を持ったプリローダーとなっています。実案件ではより多くのことを考慮する必要があります。

This movie requires Flash Player 9

00 : (準備)テンプレートを選択する

FDを起動し、新規プロジェクトを作成 > AS3 Project with Preloaderを選びましょう。下記画像を参照ください。

01 : 初期状態の構造を理解する

生成されたクラスを見てみると、Preloader.asとMain.asが展開されています。Preloader(ドキュメントクラス)がプリローダーの実装を、そしてMainが通常のコンテンツの実装を担います。簡単に仕組みを説明すると、FDのPreloader系プロジェクトを利用することにより、Flexのコンパイル時にフレームが生成されます。そして1フレーム目にプリローダーが、2フレーム目にコンテンツの実装が配置されるかたちになります。これは冒頭で紹介したFlash IDEの方法と全く同じですね。
(下記画像参照)

というわけで、AS3 Project with Preloaderを選択するだけで、下準備はFDが全て行ってくれるのです。あとは、プリローダーとコンテンツを実装するだけです。以下にポイントを挙げておきます。

▼Preloader コンストラクタ

26行目 : エンターフレームイベントをリスン > フレームを監視して「現在のフレーム == トータルフレーム」になったらロード完了処理を実行します。
27行目 : プログレスイベントをリスン > ロードの進捗を監視します。ここでプリローダーの幅を更新します。
28行目 : IOエラーイベントをリスン > 例外対策を施します

コンストラクタ

addEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
			
// TODO show loader ( 01 : ローディングバーの配置をします )		

▼Preloader loadingFinishedメソッド
エンターフレームハンドラのcheckFrame内で「現在のフレーム == トータルフレーム」になったとき、このメソッドが実行されます。
ローディング処理が全て完了後なので、コンストラクタで設定したイベントリスナーを全て解除します。(56行目~58行目)
その後ローディングバーを消去する演出を実装し、startupメソッドに繋げます。

loadingFinishedメソッド

private function loadingFinished():void
{
	removeEventListener(Event.ENTER_FRAME, checkFrame);
	loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
	loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
	
	// TODO hide loader ( 03 : ローディングバーを消去する演出を加えます )
	
	startup();
}

▼Preloader startupメソッド

このメソッドは変更の必要はありません。処理としては”Main”という名前のクラスを取得して、表示リストに加えています。
ローディングバーを消去したら、コンテンツを表示してくださいね。という実装です。

//Mainクラスを表示リストに加えます。
private function startup():void
{
	var mainClass:Class = getDefinitionByName("Main") as Class;
	if (parent == stage) stage.addChildAt(new mainClass() as DisplayObject, 0);
	else addChildAt(new mainClass() as DisplayObject, 0);
}

02 : 実際にローディングバーを実装してみる

あくまで基礎ということで、スムージング(線形補間)をかけたり、凝ったローディングバーの消去モーションを入れたり、全画面表示に対応したりといったことは一切行っていません。後日ステップアップするための記事を書こうと思います。

今回のポイントはPreloaderクラスにつきるので、その他のクラスについては掲載は割愛させていただきます。
(サンプルには全クラスが含まれています)

▼Preloader コンストラクタ

インスタンスメンバとして、barBGとbar、tfを宣言します(同時にインスタンス化も行っています)。TextFieldEXクラスについてですが、特殊なことをしている訳ではなく、テキストフォーマットの設定や初期値のストリング設定など、Preloaderクラスに実装すると煩雑になるので切り離しただけです。

private var barBG:Square = new Square(640, 0xFF0000, 1);//ローディングバーの背景
private var bar:Square = new Square(640, 0x0, 1);//ローディングバー
		
private var tf:TextFieldEX = new TextFieldEX();//初期設定済みのテキストフィールド

▼Preloader progressメソッド

ローディングバー/テキストフィールドの更新はここで行っています。少しだけ特殊な処理と言えば、「>>0」によるintキャストになるかと思います。これは小数点を持つNumber型の値を、整数であるint型へ変換する処理です。

progressメソッド

private function progress(e:ProgressEvent):void
{
	// TODO update loader ( 02 : ロード状況を監視します )
	
	/*
	 * e.bytesLoadedは読み込まれたバイト数、e.bytesTotalはトータルのバイト数です。
	 * e.bytesLoadedの最大値はトータルのバイト数なので、「e.bytesLoaded / e.bytesTotal」は
	 * 0~1の間を取ります。それをbar.scaleXに代入することで、バーを伸ばす訳です
	*/
	var percentNum:Number = e.bytesLoaded / e.bytesTotal;
	bar.scaleX = percentNum;
	trace( "percentNum : " + percentNum );
	
	var percent:int = 100 * percentNum >> 0;//percentNumは0~1の値なので、それに100をかけてパーセントにします
	tf.text = "loading... " + percent + "%";//テキストフィールドに反映させます
}

Preloader

package
{
	import caurina.transitions.Equations;
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.text.TextField;
	import flash.utils.getDefinitionByName;

	/**
	 * ...
	 * @author kickbase
	 */
	[SWF(width = "640", height = "480", frameRate = "30", backgroundColor = "#ffffff")]
	 
	public class Preloader extends MovieClip
	{
		private var barBG:Square = new Square(640, 0xFF0000, 1);//ローディングバーの背景
		private var bar:Square = new Square(640, 0x0, 1);//ローディングバー
		
		private var tf:TextFieldEX = new TextFieldEX();//初期設定済みのテキストフィールド
		
		public function Preloader()
		{
			if (stage) {
				stage.scaleMode = StageScaleMode.NO_SCALE;
				stage.align = StageAlign.TOP_LEFT;
			}
			addEventListener(Event.ENTER_FRAME, checkFrame);
			loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
			loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
			
			// TODO show loader ( 01 : ローディングバーの配置をします )
			
			barBG.y = stage.stageHeight / 2 ;
			addChild(barBG);
			
			bar.y = stage.stageHeight / 2 ;
			bar.scaleX = 0;//スケールXを0にしてバーの幅を0にしておく
			addChild(bar);
			
			//パーセント表示
			
			tf.x = 2;
			tf.y = stage.stageHeight / 2 + 6;
			addChild(tf);
		}
		
		private function ioError(e:IOErrorEvent):void
		{
			trace(e.text);
		}

		private function progress(e:ProgressEvent):void
		{
			// TODO update loader ( 02 : ロード状況を監視します )
			
			/*
			 * e.bytesLoadedは読み込まれたバイト数、e.bytesTotalはトータルのバイト数です。
			 * e.bytesLoadedの最大値はトータルのバイト数なので、「e.bytesLoaded / e.bytesTotal」は
			 * 0~1の間を取ります。それをbar.scaleXに代入することで、バーを伸ばす訳です
			*/
			var percentNum:Number = e.bytesLoaded / e.bytesTotal;
			bar.scaleX = percentNum;
			trace( "num : " + percentNum );
			
			var percent:int = 100 * percentNum >> 0;//percentNumは0~1の値なので、それに100をかけてパーセントにします
			tf.text = "loading... " + percent + "%";//テキストフィールドに反映させます
		}
		
		//フレームを監視して全てのフレームを読み込んだらロード完了メソッド(loadingFinished)を実行します
		private function checkFrame(e:Event):void
		{
			if (currentFrame == totalFrames)
			{
				stop();
				loadingFinished();
			}
		}
		
		private function loadingFinished():void
		{
			removeEventListener(Event.ENTER_FRAME, checkFrame);
			loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
			loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
			
			// TODO hide loader ( 03 : ローディングバーを消去する演出を加えます )
			
			removeChild(barBG);//ローディングバーの背景を表示リストから削除
			barBG = null;
			removeChild(bar);//ローディングバーを表示リストから削除
			bar = null;
			removeChild(tf);//テキストフィールドを表示リストから削除
			tf = null;
			
			startup();
		}
		
		//Mainクラスを表示リストに加えます。
		private function startup():void
		{
			var mainClass:Class = getDefinitionByName("Main") as Class;
			if (parent == stage) stage.addChildAt(new mainClass() as DisplayObject, 0);
			else addChildAt(new mainClass() as DisplayObject, 0);
		}
	}
}

サンプルのダウンロード


ページトップへ