Monthly Archives: October 2010

now in progress

「アラ、終わる気しないですね」の波が何度も押し寄せて来ちゃってる。

shaking typography with bookmarklet

リンクをクリック!もしくはリンクをブックマークバーまでドラッグして好きなページでクリック!

SHAKE IT

using embedded font in generated text field

ライブラリパネルで作ったフォントをasで生成したTextFieldに反映する方法メモ。ここで欲しいのはTextFormatのfontに受け渡すフォント名。ライブラリで設定したリンケージ名からフォント名をしょっ引く関数。

こんな感じ。

function getFontName( linkageName ):String
{
       Font( new ( getDefinitionByName( linkageName ) as Class )() ).fontName;
}

使う時はこんな感じ

var tf:TextField = new TextField();
tf.embedFonts = true;
tf.text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

var fmt:TextFormat = new TextFormat();
fmt.font = getFontName( "myFont" );

tf.setTextFormat(fmt);

addChild(tf);

パッケージ化したらこんな感じ

package net.sourcelab.utils
{
	import flash.text.Font;
	import flash.utils.getDefinitionByName;
	
	/**
	 * ...
	 * @author Bouze
	 */
	public class FontUtil 
	{
		/**
		 * フォントのリンケージ名から内部参照用のフォント名を取得する
		 * @param	linkageName	リンケージ名
		 * @return	フォント名
		 */
		public static function getFontName( linkageName:String ):String
		{
			return getFont( linkageName ).fontName;
		}
		
		/**
		 * フォントのリンケージ名からFontオブジェクトを取得する
		 * @param	linkageName	リンケージ名
		 * @return	Fontオブジェクト
		 */
		public static function getFont( linkageName:String ):Font
		{
			return Font( new ( getDefinitionByName( linkageName ) as Class )() );
		}
	}
}

simpleXML manners

<data>
	<elem name="A" age="10"/>
	<elem name="B" age="20"/>
	<elem name="C" age="30"/>
</data>

みたいなxmlの、nameがAのelemのage、要するに10をsimpleXMLで取得しゅる方法。

まずxmlを読み込んで、

$xml = simplexml_load_file("data.xml");

xpathでnameがAのエレメントを抽出する。

$elem = $xml->xpath('//elem[@name="A"]');

$elemがsimpleXMLElementオブジェクトなのでstring型にキャストする。

$age = (string) $elem[0]["age"];
echo $age;
//10

このstringにキャストする部分でだいぶハマった。直感的なようで直感的でないsimpleXML。

to do something syncronizing sound

Flashで曲の再生に正確に同期してごにょごにょしたい時のメモ。Soundboothを使ってマーカーを埋め込むと曲の再生時間に紐づいてイベントが発行されるのでタイミングのズレがなく同期できる。

まずSoundboothにてキューイベントを発行したい場所にマーカーを配置。

マーカーパネルで名前、パラメータを編集し、マーカーのタイプをイベントにする(←これ重要)。

マーカーの配置が完了したら別名で保存から「FLV | F4V」形式で書き出す。書き出し設定のビデオを書き出しのチェックを外して、マルチプレクサタブのFLVにチェックを入れる。オーディオタブでオーディオの設定をして「OK」で書き出し。

通常通りflvを読み込み、onCuePointにハンドラを張る。onCuePointは再生箇所がSoundboothで設定したマーカーの地点まで来た時に自動で呼び出される。引数に詳細情報を含んだObjectが渡される。

var nc:NetConnection = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
var video:Video = new Video();
video.attachNetStream(ns);

var myClient:Object = new Object();
myClient.onMetaData = function(info:Object):void
{
}

//ここでonCuePointを受け取る
myClient.onCuePoint = function(info:Object):void
{
       trace("name:"+info.name);
       trace("time:"+info.time);
       trace("parameter:"+info.parameters.tick);
};
ns.client = myClient;
ns.play("sound.flv");

詳細情報を含んだObjectのパラメータはnameにマーカーの名前が、timeにマーカーの配置された時間(ミリ秒)が、parametersにSoundboothのマーカーパネルで設定したパラメータが名前と値が対で含まれている。

このやり方だと外部flvを読み込まなくてはいけないので、サウンドデータをファイルに埋め込んでしまいたい場合はSoundboothのマーカー情報をxmlで書き出し、Flash側でイベントの発行すればいい。

xmlの書き出しはSoundboothでマーカーを設定した後、「ファイル→書き出し」からできる。このxmlにはマーカーごとに時間と名前パラメータなどonCuePointで受け取れる情報はすべて入っている。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<FLVCoreCuePoints Version="1">
	<CuePoint><Time>1566</Time><Name>0</Name></CuePoint>
	<CuePoint><Time>1813</Time><Name>1</Name></CuePoint>
	<CuePoint><Time>2255</Time><Name>2</Name></CuePoint>
</FLVCoreCuePoints>

あとはFlash側でこのxmlを読み込み、音楽の再生時間を監視し続けながら、マーカーの時間が来たらしかるべき処理をすればいい。

//ライブラリから音楽データを読み込む
music = new Music() as Sound;
//30fpsで現在の再生時間を見にいく
timer = new Timer(1000 / 30);

//マーカー情報を持ったxmlを読み込みパースする
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, function(e:Event)
{
       var xml:XML = new XML(loader.data);
       var length:int = xml.CuePoint.length();
       var setting:Vector.<Vector.<int>> = new Vector.<Vector.<int>>(length, true);

       for (var i:int = 0; i < length; i++)
       {
               setting[i] = new Vector.<int>(3, true);
               setting[i][0] = int(xml.CuePoint[i].Name);
               setting[i][1] = int(xml.CuePoint[i].Time);
               //通過済みチェックフラグ
               setting[i][2] = 0;
       }

       //音楽と監視開始
       sc = music.play();
       timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void
       {
               for (var i:int = 0; i < length; i++)
               {
                       //再生中の時間がキューポイントの時間を超えて、かつ通過済みでなければ
                       if ( setting[i][1] <= sc.position && !setting[i][2] )
                       {
                               trace("cue name:" + setting[i][0]);
                               trace("cue time:" + setting[i][1])
                               //通過済み
                               setting[i][2] = 0;
                               return;
                       }

                       if ( sc.position > music.length )
                       {
                               trace("再生終了")
                       }
               }
       });
       timer.start();
);
loader.load(new URLRequest("cuePoints.xml"));