Home

blog.cuegraphix.com

共有オブジェクトのリンケージクラスを生成するときの対策

共有オブジェクトとして書き出したリンケージクラスを、読み込み側SWFでインスタンス生成するときにはまったのでメモ。

起こったこと。

  1. MovieClipクラスを継承したSheardMovieClipクラスを作成します
  2. Flash上でムービークリップを作成し、いくつかのムービークリップを配置します。
    そしてそれらにインスタンス名をつけます。(ここではmc1,mc2とします。)

    SheardMovieClip (クラス名:SheardMovieClip、ランタイム共有用に書き出し)
    ├mc1 (インスタンス名:mc1)
    └mc2 (インスタンス名:mc2)
  3. 共有ライブラリSWFを書き出し
  4. このSheardMovieClipを読み込み側Flashにコピーして、プロパティでランタイム共有用に読み込みとなるよう設定します。
  5. そして読み込み側でインスタンス生成します。
    new SheardMovieClip();
    

として読み込み側SWFを書き出すとReferenceErrorが発生!

ReferenceError: Error #1056: SheardMovieClip のプロパティ mc1 を作成できません。

共有ライブラリSWFを書き出すときには何もなかったのに、共有ライブラリとして読み込むと、参照できないというか中のムービークリップの名前(プロパティ)を作成できないと言われる。
SheardMovieClipクラスに参照プロパティを作ってみる。

public var mc1:MovieClip;
public var mc2:MovieClip;

そして読み込み側SWFを再度書き出し。

お、何も言われない。

と思って、今度は共有ライブラリSWFを書き出してみると

1151: 定義 mc1 (名前空間 internal) にコンフリクトが存在します。

を怒られる。。
まぁそりゃそうだわな~と思いながら10分ほど悩む。

共有ライブラリFlashのパブリッシュ設定で「ActionScript設定」→「ステージのインスタンスを自動宣言」のチェックをはずすことで解決しました。

もしくはSheardMovieClip クラスをdynamicクラスにして、インスタンスを取得するときはgetChildByNameで参照する方法もあり。

PreloaderとListenコマンド(2)

前回に引き続き、もう少しだけListenコマンドを触ってみる。

コンテンツに入る前にイントロムービーを流したいなどはよくある話だと思います。
メインコンテンツを長々読み込んだあとに、またイントロ用のローディングなんてのはあまりふつくしくないので、Preloaderでメインコンテンツを読み込む前に流してしまおうというテストです。

ムービーが再生終了した後にメインコンテンツを読み込むようにします。
しかしイントロムービーの場合往々にしてスキップボタンも必要になってくることが多いと思います。
そのどちらものイベントでコマンドを抜けるようにすればいいので、ほかのイベントと干渉しないよう新たにイベントクラスを作ってしまうほうが確実で簡単かと思います。

public class PreloadEvent extends Event
{
	
	public static const PRELOAD_COMPLETE:String = "preloadComplete";
	
	public function PreloadEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
	{
		super(type, bubbles, cancelable);
		
	}
	
	public override function clone():Event
	{
		return new PreloadEvent(type, bubbles, cancelable);
	}
	
	public override function toString():String
	{
		return formatToString("PreloadEvent", "type", "bubbles", "cancelable", "eventPhase");
	}
	
}

と、完了イベントを持つイベントクラスを用意して2つのイベントが起こった際に、preloadCompleteを送出するようにします。

private function _introComplete( e:Event ):void
{
	// PreloadEvent.PRELOAD_COMPLETEイベントを送出
	dispatchEvent( new PreloadEvent( PreloadEvent.PRELOAD_COMPLETE ) );
}

protected override function _onCastLoadStart():void {
	
	var player:FLVPlayback = FLVPlayback( getChildByName( "introPlayer" ) );
	player.addEventListener( VideoEvent.COMPLETE, _introComplete );
	
	skip.addEventListener( MouseEvent.CLICK, _introComplete );
	
	player.play( "intro.flv" );
	
	addCommand(
		new Listen( this, PreloadEvent.PRELOAD_COMPLETE, { timeOut: 0 } ),
		new Trace( "イントロが終了しました" ),
		new RemoveChild( this, player ),
		new RemoveChild( this, skip )
	);
}

{ timeOut: 0 }は忘れずに。(よく忘れる・・・オデ)

んでテキトーにイントロで使ったものを削除すれば、このあとメインコンテンツのローディングが開始されます。

ムービー再生中にバックグラウンドでメインコンテンツを読み込んだらもっとカコいいけどね。

PreloaderとListenコマンド(1)

PreloaderクラスはProgression2.0ではExPreloaderを継承していたものが、Progression3.0になって新たにCastPreloaderを継承することとなり大きく変わりましたね。

イベントの流れとしては

_onInit (読み込み完了 / ステージの設定など)
  ↓
_onCastLoadStart (ロードが開始される直前)
  ↓ ←登録されたCommandListの全てのコマンドの処理が
  ↓  完了すれば次へ
[メインSWFの読み込み開始]
  ↓
_onProgress (プログレスバーの表示など)
  ↓
_onCastLoadComplete
  ↓ ←登録されたCommandListの全てのコマンドの処理が
  ↓  完了すれば次へ
[メインSWFをドキュメントの表示リストに追加]

という流れらしい。
なので以前はロードが開始して読み込み終わるまで止めることのできなかったので、本当にローディングの処理しかできなかったけれど、ロード開始直前とロード完了直後のCommandListにより、幅広い表現ができますね。

たとえば、
「このコンテンツには音声が含まれます。ヘッドフォンのボリューム上げてね」みたいなアテンションとか、「HTML版」「Flash版」みたいな振り分けページがFlashページでできる。
早く見たいときに散々メインコンテンツ読み込んでからでないとHTML版の表示ができないのは本当にストレスですからねぇ。。。

そんなとき使えるのがListenコマンド!
Preloaderとか、ページ遷移の前に規約を読ませるみたいなわざわざScene作るのがめんどくさい時くらいしか使い道が思いつかないListenコマンドw
でも使い出すとすごく便利かもしれない。

Listenコマンドはイベントを送出するdispatcherと受け取りたいイベントの種類の名前を渡すことで、そのイベントが起こるまで待機してくれます。
flashButtonとhtmlButtonというインスタンスがあるとして

protected override function _onCastLoadStart():void {
	htmlButton.addEventListener( MouseEvent.CLICK, function():void { navigateToURL( new URLRequest( "html.html" ) ); } );
	addCommand(
		[
			new AddChild( this, flashButton ),
			new AddChild( this, htmlButton )
		],
		new Listen( flashButton, MouseEvent.CLICK, { timeOut: 0 } ),
		new Trace( "Flash版ボタンがクリックされました" ),
		[
			new RemoveChild( this, flashButton ),
			new RemoveChild( this, htmlButton )
		]
	);
}

とすれば、Flash版のボタンを押されたときにのみメインコンテンツのロードを行います。
Listenコマンドを使用する際は、第3引数でtimeOutを”0″にしておかないとデフォルト15秒でCommandTimeOutErrorエラーが発生しコマンドリストが終了します。
(ただ終了しても問題なく動くように見えるんですけどね。。。でもエラーが出るのはいやなので設定必須)

次は複数のlistenerを管理する場合のことについて書いてみます。

SceneObjectのaddSceneFromXMLについてのメモ

Progression3都物語で勉強してきたことやけど、よく忘れそうなので今になってメモ。

protected override function _onLoad():void {
	// 実行したいコマンドを登録します。
	addCommand(
		// XML ファイルを読み込みます。
		new LoadURL( new URLRequest( "index.xml" ) ),
		// 匿名関数を実行します。
		function():void {
			// 読み込んだ XML ファイルから子シーンを作成します。
			addSceneFromXML( new XML( this.latestData ) );
		}
	);
}

とする際、XMLのcls属性のString型からgetDefinitionByNameでクラスの参照を生成する際に、「クラス名が定義されてないよ」とReferenceErrorを投げ返してきます。

なので、コンストラクタなどで

public function IndexScene( name:String = null, initObject:Object = null ) {
	// スーパークラスを初期化します。
	super( name, initObject );

	// クラスが SWF ファイルに含まれるように参照しておきます。
	MyScene1;
	MyScene2;
	MyScene3;
	MyScene4;
}

という感じで、ただ参照するためにクラス名のみを書いておくとエラーなく動作します。

Home

Search
Feeds
Meta

Return to page top