京ぽん2(WX310K)Flash Knowhow & Tips

京ぽん2向けFlashアプリ開発に関する情報を載せます(割と自分用

Last Update May09,2006(Since Feb28,2006)

インターフェイス

キー入力

KeyListenerでやるのがよさげ。onKeyなんたらは使わない方がよいらしい。

keyListener = new Object();
keyListener._parent = "not defined";
keyListener.target_mc = this;

//キーが押されたときに呼ばれる関数
keyListener.onKeyDown = function() {
	code = Key.getAscii(); //キーコードの取得
		if(code==0)code=Key.getCode();
		switch (code){
				//フォーカスが来ていなくても拾えるキー
				case 32: //center key
				case 35: //#
				case 42: //*
				case 48: //0
				case 49: //1
				case 50: //2
				case 51: //3
				case 52: //4
				case 53: //5
				case 54: //6
				case 55: //7
				case 56: //8
				case 57: //9
				case 0: //mail,talk

				//フォーカスが無いと拾えないキー
				case 37: //left
				case 38: //up
				case 39: //right
				case 40: //down
		}
}
Key.addListener(keyListener);

htmlから情報の受け取り

flashでは、

flash.swf?foo=bar&hoge=fuga

といった形式でflashへ変数を渡すことが出来る。しかし、京ぽん2のローカルアプリでは、この形式の指定ができないため、
HTMLファイルにembedまたはobjectでswfファイルを埋めこみ、FlashVarsを用いて 変数を渡す必要が有る。

<embed src="flash.swf" FlashVars="foo=bar&hoge=fuga">
</embed>
<object data="flash.swf">
<PARAM NAME=FlashVars VALUE="foo=bar&hoge=fuga">
</object>

flash側からは以下のように参照することができる。

fo = _root.foo;
ho = _root.hoge;

この方法でflashに変数を渡せるようになったが、
html中にflashを埋め込んでいるため、Flashからキー入力が拾えないという致命的な欠陥がある。
しかし、sharedObjectを使用することによりこの問題を回避することが可能である。

外部から変数が渡されているときは、その値をSharedObjectに保存して swfファイル自分自身を単体で開く。
単体で開いた場合(外部から変数が与えられていないとき)にはSharedObjectの内容を読み出して使用する。
もちろん、この時はswfファイルが単体で開かれているのでキー操作が出来るようになる。

myLocalSO = sharedobject.getLocal("myso");//shared objectの準備
this.onLoad = function() {
	if (_root.url.length>0){  //htmlから呼ばれたときには、urlという変数に値が入っているとする。
		myLocalSO.data.url = _root.url;  //SharedObjectに情報を保存
		myLocalSO.flush();  //SharedObject情報の強制更新
		getURL(_level0._url);  //自分自身を開く
	}else{ //単体で開かれたとき
		myurl=myLocalSO.data.url;
		//各種処理 略
	}
}

京ぽん2向けのFlashアプリには有用なテクニックだが、これを組み込むとPC上でのデバグ作業がかなり面倒になる場合があるので、
ある程度基礎ができあがってから組み込むと良いと思われる。

外部ファイル読み込み

sound.loadSoundやloadvars.loadなどで外部ファイルを読み込んで使用することが出来る。

本体内蔵データフォルダから読み込む場合は

file://localhost/D:/data/(ファイル名)

miniSDから読み込む場合は

file://localhost/F:/(ファイル名)

として読み込む。

ファイル名・パスに日本語を含む場合、useCodepageをfalseにしてから日本語の部分をescapeして読み込む。
日本語を扱うときは、useCodepageのtrue,falseを使い分ける必要が有る。
通常はtrueでいいかと思う。

system.useCodepage=false;
location="file://localhost/F:/" + escape("俺のファイル.txt");
//foo.load(location);

LoadVars

LoadVarsは、

foo=bar
hoge=fuga
・
・
・

[ 変数名=値 ]の形式のテキストファイルを読み込むためのものである。
読み込むデータがこの形式になっているならそのまま利用すればよい。
裏技的だが、無理をすればテキストファイル一般を読み込むことが出来る。
下に掲載するコードは、拙作のmp3プレーヤから抜き出したものだが、
かなりアレなのでバグ・問題が発生しない保証はない。非推奨。
少しはマシな方法が他にあるようだ。

lines = new Array(); //ファイルのn行目→lines[n]という形で読み込まれる
myLoadVars= new LoadVars;
myLoadVars.load("foo.txt");
myLoadVars.onLoad=function(success){
	if(success){
		system.useCodepage=true; //SJISのファイルを読むために必須
		vars_to_string=myLoadVars.toString();
		lindex=vars_to_string.lastIndexOf("&onLoad=%5Btype%20Function%5D");
		if( lindex != -1)
			vars_to_string=vars_to_string.substr(0,lindex-1); //ゴミを除去
		if( vars_to_string.charAt(vars_to_string.length-1) == "=")
			vars_to_string=vars_to_string.substring(0,vars_to_string.length-1);//末尾につくゴミの"="を除去
		while((p=vars_to_string.indexOf("%0D%0A")) != -1){
			vars_to_string=vars_to_string.substr(0,p) + "%0A"+ vars_to_string.substr(p+6);
		}
		while((p=vars_to_string.indexOf("%0D")) != -1){
			vars_to_string=vars_to_string.substr(0,p) + "%0A"+ vars_to_string.substr(p+3);
		} //改行コードを0Aに統一してしまう
		vars_to_string=unescape(vars_to_string);
		lines=vars_to_string.split("\n");
	}else{
		//読み込み失敗
	}
}

mp3ファイル再生関係

ローカルのmp3ファイルを再生する場合、loadSoundの第二引数をFalseにしないとブラウザが落ちる。
httpでネットワーク上のファイルを読むにはTrueでもいいっぽい。

mysnd = new Sound;
mysnd.loadSound("hoge.mp3",false);

いちおー、onLoadで拾って読み込みが完了してから再生するようにする方が良いと思う。

mysnd = new Sound;
mysnd.onLoad = function(success){
	if(success){
		mysnd.start();
}
mysnd.loadSound("hoge.mp3",false);

Flashから読み込めるmp3の容量の限界は約5MBだが、これに満たない容量のものでも連続で読み込むと容量制限にかかる。
ただし、前のmp3の再生が終わっていれば問題ない(っぽい。

//BAD SAMPLE
mysnd.loadSound("foo.mp3",false);

//foo.mp3の再生がおわらないままbar.mp3を読み込む
mysnd.loadSound("bar.mp3",false);
//きっとフリーズする

この問題は、Soundオブジェクトをdeleteで破棄して作り直せば回避できる。
ローカルファイルを再生する場合はmysnd.loadSound("",false);というダミーを一行入れるだけでも回避可能である。
ネット上のファイルをストリーミングで再生する場合は真面目に破棄&再生成すべし。

//BETTER SAMPLE
mysnd.loadSound("foo.mp3",false);

//foo.mp3の再生がおわらないままbar.mp3を読み込む
mysnd.loadSound("",false); //これがあると
mysnd.loadSound("bar.mp3",false);
//固まらないハズ

再生完了はmysnd.onSoundCompleteで拾える

//曲の再生が終わったら次の曲へ
mysnd.onSoundComplete = function(){
	nexttrack();
}

ネット上のファイルを再生する場合

httpで読み込む場合は、読み込んだ容量を監視したほうがよさげ。
ストリーミングしないなら。
それから、落ちてこないときは適当にタイムアウトするようにしたほうがいいと思う。

function kansi(){ //http時用、読み込み容量監視
	if(mysnd.getBytesTotal() > 0){
		if(mysnd.getBytesLoaded()==mysnd.getBytesTotal()){//読み込みが完了した
			clearInterval(myInterval);
		}
	}else{
		message=Math.floor(mymp3.getBytesLoaded()/1024)+"KB / "+Math.floor(mymp3.getBytesTotal()/1024)+"KB ( "+Math.floor(mymp3.getBytesLoaded()/mymp3.getBytesTotal()*100)+"% )";
		//  読み込んだ容量/全体の容量(%)
	}
}
mysnd.loadSound("http://example.com/hoge.mp3",false);
myInterval = setInterval(kansi,300);

ストリーミング再生について。
ストリーミングで再生していると、こいつは再生開始時点からデータを全部メモリに溜め込んでしまう。
メモリいっぱいに溜まると当然(orz)固まるので、適当に捨ててやらないとならない。
flash Player 7ならばストリーミング時でもgetBytesLoaded & getBytesTotalが取得できるのでこれを使えばよし。
しかし、京2のflash Player 6ではなんか取得できねーので、ビットレートと時間から計算する。
書くまでもないですが、ビットレート/8*秒でキロバイト。時間は1000分の1秒単位で出てくるので、1000で割る。

if(mysnd.position>0){  //経過時間が正 : 再生が行われてる状態。
		loaded_kb=Math.floor(cast_data[id_playing].bit/8*mysnd.duration/1000);  //容量算出
		msg=loaded_kb+"KB:"+((mysnd.duration>mysnd.position)?Math.floor((mysnd.duration-mysnd.position)/1000):0)+"秒バッファ";
		//全体の秒数と現在の時点の差からバッファ時間を算出
	if(loaded_kb>2000){  //適当な容量溜まったらsoundオブジェクトの破棄やらなにやらをやる。swfファイルが消費するメモリによって調整する。
		start_playing();
	}
}else{  //再生が始まってない状態をバッファ中と解釈。
	msg="バッファ中("+Math.floor(mysnd.duration/100)/10+"秒)";
}

PCで試すと分かるが、getBytesほげほげで取得するのと、時間から計算するのとでは若干誤差がある。
が、まあそんなんはうまく調整しるってことで。

soundオブジェクトのなんか。こんなんでいいっしょ、たぶん。

function create_mysnd(){
	if(mysnd!=undefined){
		delete mysnd;
	}
	mysnd = new Sound;
}