Hatena::ブログ(Diary)

独学ActionScript このページをアンテナに追加 RSSフィード

2008.09.17

プロフェッショナル タイトル ジェネレーター (3)タイマーとサウンド

前回の素材をベタベタ並べたコードに、タイマーを使った時間差のある表示と、効果音(.mp3ファイル)の再生、を追加しました。やっとFlashっぽくなってきた。


メモ

// 2秒後に再生開始のタイマー追加
var timer:Timer = new Timer(2000, 1);
timer.addEventListener(TimerEvent.TIMER, onLoadSound, false, 0, true);
timer.start();

キャッチコピーを時間差表示するためのタイマー追加箇所。このaddEventListenerの書き方(false, 0, trueの部分)は、初めてのActionScript 3.0推奨されている書き方です。

private function onLoadSound(event:TimerEvent):void 
{
	// リスナー削除
	event.target.removeEventListener(TimerEvent.TIMER, onLoadSound);
	
	// ピアノトーンSEの読み込み
	var sndPianoTone:Sound = new Sound();
	sndPianoTone.load(new URLRequest("../0000/ptg_pt32k.mp3"));
	
	// mp3ファイルのロードエラー時の処理
	sndPianoTone.addEventListener(IOErrorEvent.IO_ERROR, onIOError, false, 0, true);

	// mp3ファイルのロード完了時の処理
	sndPianoTone.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true);
}

private function onIOError(event:IOErrorEvent):void 
{
	trace("サウンドのロード時にエラーが発生しました:", event.text);
}

2秒経ったらピアノトーンのSE(ptg_pt32k.mp3)を読み込み、その読み込みイベントに2つのリスナーを追加します。1つは読み込み失敗、もうひとつは読み込み完了。

private function onLoadComplete(event:Event):void 
{
	// リスナー削除
	event.target.removeEventListener(Event.COMPLETE, onLoadComplete);
	
	// サウンド関係の変数
	var channel:SoundChannel = new SoundChannel();
	var localSound:Sound = event.target as Sound;
	var trans:SoundTransform = new SoundTransform();
	
	// ピアノトーンSEの再生
	channel = localSound.play();
	
	// ボリュームを50%に
	trans.volume = 0.5;
	channel.soundTransform = trans;
	
	// キャッチコピー表示の遅延処理
	var timer:Timer = new Timer(100, 1);
	timer.addEventListener(TimerEvent.TIMER, showCatchCopy, false, 0, true);
	timer.start();
}

private function showCatchCopy(event:TimerEvent):void 
{
	// リスナー削除
	event.target.removeEventListener(TimerEvent.TIMER, showCatchCopy);
	
	// キャッチコピーのテキストフィールドを追加
	addChild(txtFldCC);
}

読み込みが正常に完了(onLoadComplete)したら、読み込んだmp3ファイルを再生し、若干ずらして(0.1秒)キャッチコピーを再生しています。

【AS3入門】イベントリスナーで使用を推奨されるオプションパラメータuseWeakReference

初めてのActionScript 3.0」の中で出てくるコラムガベージコレクション:イベントリスナーに関して推奨するオプションパラメータ」(56〜57ページ)では、addEventListenerのオプションパラメータであるuseWeakReferenceを使用することを推奨しています。このコラムによると、これを手動設定することで詰めが甘いコードの管理によって発生するメモリ管理の問題に直面することはほぼなくなる、としています。

eventTarget.addEventListener(EventType.EVENT_NAME, eventResponce, useCapture:Boolean, priority:int, useWeakReference:Boolean);

3つの太字の部分が使用可能なオプションパラメータで、一般的には省略することが多いようです。初期値はfalse, 0, falseです。最後のuseWeakReferenceが今回使用を推奨しているパラメータで、手前2つのパラメータ(useCaptureとpriority)は、デフォルトのままで良いとのこと。

3つめのオプションパラメータ useWeakReference は、ここで理解し、この先使用してもらいたいオプションです。手っ取り早くいうと、このパラメータは、不要になったリスナーの削除に万一注意を怠った場合でも、メモリ管理を助ける働きをしてくれるのです。

(中略)

どんなにがんばっても、開発者がコード内でイベントリスナーを削除し忘れるのは珍しいことではありません。しかし、これには遠く及ばないものの次善の策として、リスナーへの弱参照という方法があります。簡単にいうと、弱参照に設定されたリスナーはガベージコレクターに管理されないので、削除用のマークを手動でつける必要がないのです。オブジェクトを使い終わった後、オブジェクトへの弱参照のみが残っている場合には、そのオブジェクトガベージコレクションの対象になります。

初めてのActionScript 3.0

ちょっと難しいけど、addEventListenerで追加したイベントの中でremoveEventListenerでちゃんと削除しなかったリスナーがあった場合に、このパラメータを設定しておけば使い終わったリスナーをガベコレが削除してくれる確率がアップするよ!ってことでしょうか。そんな素敵パラメータがあるのなら最初からデフォルトでONにしておいて欲しい感じがしますが、そうなっていないということは何かデメリットがあるような気がしないでもない…。

ActionScript 3.0 コンポーネントリファレンスガイドでuseWeakReferenceのパラメータを調べてみると、以下のように書いてありました。

useWeakReference:Boolean (default = false) ― リスナーへの参照が強参照と弱参照のいずれであるかを判断します。デフォルトである強参照の場合は、リスナーガベージコレクションが回避されます。弱参照では回避されません。

flash.events.EventDispatcher (ActionScript 3.0)

この強参照とか弱参照ってのがイマイチわからないんですけど、

  • 強参照=falseの場合(デフォルトの設定) ──自分でちゃんと管理して忘れずにremoveEventListener出来る人向け。忘れるとメモリ使いまくりの罠にはまることもある(?)
  • 弱参照=trueの場合(コラム推薦の設定) ──普通の使い方をする分には、弱参照によってリスナーを消し忘れてもガベコレが自動削除してくれる初心者向け。高度な使い方をするときには弊害が出る可能性がある(?)

って感じでしょうか。クエスチョンマーク付きの部分は素人の妄想ですのでお察しをw とりあえず自分はバリバリの初心者ですので、この参考書に従い以下のコラム推薦パラメータを使ってイベントリスナーを使っていこうと思います。高度な使い方が出来るようになって、その際にこの設定がどんな影響を与えるのか理解できる日がもし仮に奇跡的に来れば、ここに追記したいと思います。

われわれの好みとして、かつ本書で今後使う慣行として、addEventListener() は次のシンタックスで使用することにします。

eventTarget.addEventListener(EventType.EVENT_NAME, eventResponse, false, 0, true);

このシンタックスを使用する慣習がつくと、詰めが甘いコードの管理によって発生するメモリ管理の問題に直面することはほぼなくなります。ただし、この方法は不必要になったリスナーを明示的に削除する方法の代替ではなく、あくまでも予備的なプランであり、習得の容易なプラクティスであることを覚えておいてください。

初めてのActionScript 3.0

確かに、このコラム以降に出てくるサンプルプログラムは、すべて上記の書き方で統一されています。よって、ほとんどの場合においてはメリットだけを享受できる素敵な設定だと素人的には思います。またコラムの最後では、あくまでも一番重要なのはちゃんと自分でリスナーを管理して削除することだと強調しています。


わかりやすい解説ページがありました

(2008.09.22 07:04 追記)

アドビ上条さんブログに、上記のオプションパラメータや参照の方向についてのとてもわかりやすい解説記事がありましたので追記します。

akihiro kamijo: イベントリスナ (AS3) とガーベジコレクション

この記事を読んで、そもそも自分は参照の強弱より参照の方向すら理解できていないことを理解できました! ですが、前述のイベントリスナーオプションパラメータに関しては、上条さんもまったく同じ事をオススメしているので、このuseWeakReferenceが素敵パラメータであることは間違いなさそうです。

都合の良いことに、イベントリスナの登録時に弱い参照を使うかどうかを指定することができます。addEventListener() の5 つ目の引数を true にすれば弱い参照が使われます。

addEventListener(”type”, listener, false, 0, true)

3 つ目と 4 つ目の引数は false と 0 を指定しておけば大抵問題ありませんので、上の形を覚えておけば大丈夫です(たぶん)。今後イベントリスナを登録する際はこれを使うように決めてしまうというのも結構お勧めかもしれません。

akihiro kamijo: イベントリスナ (AS3) とガーベジコレクション

上記は素敵パラメータuseWeakReference部分だけの引用ですが、なぜこれが素敵なのかわかりやすく解説されているので記事全文を読むことをおすすめします。


まとめ

このシリーズのエントリーは、「AS3入門」のまとめにまとめてあります。