[AS]配列で任意の位置に値を追加する方法

配列で指定した位置に値を追加する方法。
指定した位置を削除するときと同じArray.splice()を使う。

以下、削除、追加のソース

var array:Array = ["a","b","c"]
trace(array); //出力:a,b,c
var number = 1;
array.splice(number,1);
trace(array); //出力:a,c
array.splice(number,0,"d");
trace(array);//出力:a,d,c

[AS]TextField.defaultTextFormatを複数作って、TextFormatを追加していける

defaultTextFormatの挙動について、
名前の通り、TextFieldに設定されている、TextFormatを一度デフォルトに戻してから、新しいFormatを設定するものと思ったら、上塗りで追加していくことが可能でした。
(今まで検証せずに使ってた、恐ろしい・・・)

↓以下フレームアクション

var tf:TextField = new TextField();
var str:String = "ほげほげ";
tf.autoSize = "left";
addChild(tf);
//テキストフォーマット1個目
var tfm1:TextFormat = new TextFormat();
tfm1.size = 50;
//1個目を設定
tf.defaultTextFormat = tfm1
//テキストフォーマット2個目
var tfm2:TextFormat = new TextFormat();
tfm2.color = 0xFF0000;
//2個目を設定(1個目の設定を残して上塗り設定)
tf.defaultTextFormat = tfm2;
tf.text = str

一点だけ注意は、tf.text = strをTextFormat適用後に設定してること。
これは適用後にしないと、それ以後にdefaultTextFormatしても無意味。

[AS]フォーカスをステージに戻す方法(どこもクリックされていない状態)

以下、1行でOK。

stage.focus = stage;

[AS]定義と同時に実行する無名関数

こういう書き方もあるのね。

//フレームアクション
(function(){
trace("a");
trace("b");
trace("c");
})();

うまい使い道がうかばないけれども。、

[AS]文字列のURLエンコードとデコード

文字列をURLエンコードする場合は、flash.utils.escapeMultiByte()。
URLエンコードされた文字列をデコードする場合は、flash.utils.unescapeMultiByte()。

//フレームアクション
var str:String = "/hoge/moge/hage/toge/img.jpg";
str = escapeMultiByte(str)
trace(str);//出力:%2Fhoge%2Fmoge%2Fhage%2Ftoge%2Fimg%2Ejpg
str = unescapeMultiByte(str)
trace(str);//出力:/hoge/moge/hage/toge/img.jpg

参考:[AS3] URLエンコード / F-Site

[AS]画像をゆっくり動かす方法

偉い人に教えてもらったテクニック。

通常ゆっくり動かすときに1px以下だとカクカクした動きになります。

package  {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	/**
	 * ...
	 * @author 393

	 */
	public class Test extends Sprite{
		private var bm:Bitmap;
		//ライブラリに画像を用意し、クラス名Bmpでリンケージ。
		//画像サイズは400×300
		
		public function Test() {
			var bmd:BitmapData = new Bmp(0, 0);
			bm = new Bitmap(bmd);
			addChild(bm);
			
			addEventListener(Event.ENTER_FRAME , enterFrameHandler);
		}
		private function enterFrameHandler(e:Event):void {
			//かくかくと動く
			bm.x += 0.08;
			bm.y += 0.08;
		}
	}
}

スムーズに動かしたいときは、beginBitmapFill()を使えばOK。

package  {
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	/**
	 * ...
	 * @author 393
	 */

	//ライブラリに画像を用意し、クラス名Bmpでリンケージ。
	//画像サイズは400×300
	
	public class Main extends Sprite{
		
		private var matrix:Matrix = new Matrix();
		private var bmp:BitmapData;
		private var sp:Sprite;
		private var mx:Number = 0;
		private var my:Number = 0;
		private var w:Number;
		private var h:Number;
		
		public function Main() {
			bmp = new Bmp(0, 0);
			sp = new Sprite();
			addChild(sp);
			buttonMode = true;
			this.addEventListener(Event.ENTER_FRAME , xEnterFrame);
		}
		function xEnterFrame (e:Event):void {
			mx += 0.05
			my += 0.05
			matrix.tx = mx;
			matrix.ty = my;
			sp.graphics.clear();
			//smoothプロパティをtrueにするのがポイント
			sp.graphics.beginBitmapFill(bmp, matrix,false,true);
			sp.graphics.drawRect(mx, my, 400, 300);
			sp.graphics.endFill();
		}
	}
}

このときのポイントは、beginBitmapFill()の第3引数のsmoothをtrueにするということ。
(デフォルトはfalse)
falseのままだと、先のサンプルと同じくカクカクした動きとなります。

もっと簡単にできる方法を追加しました。
[AS]画像をゆっくり動かす方法 その2

[AS]ArgumentError: Error #2015: BitmapData が無効です。エラーの謎

エラー:ArgumentError: Error #2015: BitmapData が無効です。
書籍:ActionScript3.0エラーアーカイブスによると、このエラーの主な原因は、

1.BitmapDataインスタンスの幅または高さが制限範囲(1~8191px)を超えている。
2.BitmapDataインスタンスのピクセルの総数が1677215pxを超えている。

ということらしいのですが、じゃあこれはどういうことだ?ということがおきたのでメモ。

//フレームアクション
for(var i:uint = 0; i < 11; i++){//i < 10のときは実行可能
	var bmd:BitmapData = new BitmapData(4000, 4000,true,0x11FFCC00);
}

これを実行するの上記エラーになります。
(ちなみにfor文を10回繰り返しではエラーにならない。11回でエラーになる)

これは主な原因の1,2も満たしていないのでその他の原因ということでしょうか。
憶測として、BitmapDataは全体でのピクセル数の制限があるのでは?ということで、
上記の場合は、4000×4000×11 = 176000000ピクセルとなります。
このくらいが限界なのかと、ためしに、以下のように書き換えてみると同じようにエラー
(2000×8000×11 = 176000000 でピクセル総数は同じ)

for(var i:uint = 0; i < 11; i++){//i < 10のときは実行可能
	var bmd:BitmapData = new BitmapData(2000, 8000,true,0x11FFCC00);
}

うんうん、予想通り。
じゃあ、これもエラーだよねと、以下のようにすると、(1000×1000×176=176000000)
これは想定外にOK・・・

for(var i:uint = 0; i < 176; i++){//i<700くらいでやっとエラーになる。
	var bmd:BitmapData = new BitmapData(1000, 1000,true,0x11FFCC00);
}

繰り返し数を700回くらいにするとやっとエラーになります。

うーん、どういうことなんだろう。。。

これで現実的に困ったのはEnterFrameの処理でBitmapDataを生成しまくってたら、この現象になってしまったということ。
具体的には、BitmapData作って、BitmapにあててaddChildして、一定時間がたったら、そのBitmapをremoveChildして~の繰り返しをしてたのだけど、しばらく動かしているとこのエラーが発生。
一応解決策は、BitmapをremoveChildする際に、BitmapData.dispose()してあげれば大丈夫な感じだったけど、原因がはっきりしないのが、なんだか気持ち悪い。。。

※コメント欄で教えてもらいました。

[AS]動的に追加したオブジェクトは、インスタンス名(nameプロパティ)を使ってアクセスすることはできない?→できます。

できそうでできなかったのでメモ。
※2009/9/25/21:43追記 できました→下に追記があります。

前提として、ステージ上にMcを配置し、そのインスタンス名はmc
mcの中には2個Mcが配置してあり、それぞれ、mc1、mc2とインスタンス名を設定

//メインのタイムラインのフレームアクション
trace(mc["mc"+1]);//出力:[object MovieClip]
trace(mc["mc"+2]);//出力:[object MovieClip]

//動的にspriteを作って、ステージ上のmcに配置
var sp1 = new Sprite();
sp1.name = "sprite1";
mc.addChild(sp1);
trace(this.mc["sprite1"]); //出力:underfined

//動的にspriteを作って、ステージに配置
var sp2 = new Sprite();
sp2.name = "sprite2";
addChild(sp2);
trace(this["sprite2"]); //出力:underfined

//配列につっこむ
var array = [];
array.push(sp1);
trace(array[0]);//出力:[object Sprite]

動的に設定したSpriteはnameプロパティを設定しても、それを使ってアクセスってできないのかな?
とりあえず配列つっこんで保持しておけばそこから呼び出すことはできるけど。
気分的には配列作るのにちょっと抵抗あり。
うーん。

※2009/9/25/21:43 追記
コメント欄にて教えていただきました。
以下のようにすればアクセス可能。

var sp1 = new Sprite();
mc.addChild(sp1)
sp1.name = "sprite1";
mc["sprite1"] = sp1
trace(this.mc["sprite1"].name);  //出力:sprite1

ついでにもう一点。
「as3 name インスタンス名」でググッてみたらF-siteにて野中さんの詳しい解説もありました。
[AS3] MovieClipインスタンスとインスタンス名

これによるとDisplayObjectContainer.getChildByName(String)を使う手段もあり。

var sp1 = new Sprite();
mc.addChild(sp1);
sp1.name = "sprite1";
trace(mc.getChildByName(sp1.name).name); //出力:sprite1

[AS][?]FLV読み込み時のonMetaDataを取得するタイミングがわからない

ちょっと気持ち悪いのでメモ

◆現象◆
簡単なFLVプレイヤーでインターフェースは再生ボタンと、頭出しボタン。
FLVPlaybackではなく、Videoオブジェクトによる自作。
この記事にかいてあるLoadMovieクラスの拡張版のような感じ。
(実際はもっとごちゃごちゃしてるのであとで時間ができたら簡略版を作って検証・記載する、つもり)
NetStream.clientにて、onMetaDataを取得するようにしてある。
NetStream.play(“xxx.flv”)で、MetaDataが取得は問題ないのだけど、頭だしボタンを押したときもMetaDataが取得される場合がある。
(読み込むFLVファイルによっては、頭出ししてもMetaDataが取得されない場合がある)
頭出しの処理は、NetStream.seek(0);

seek(0)から再生させたときにonMetaDataを取得するということなのか?
(seek(0)のタイミングではなくって、そこから再生させたら、みたいな感じ)
flvファイルによって、上記条件でMetaDataを取得したり、しなかったりという感じが???なのです。
原因よくわからんのでとりあえず例外処理書いたけど、なんか気持ち悪い。

[JSFL][?]JSFLでモーショントゥイーン(色)させる

久しぶりにタイムラインでの作業。
MCのカラーを黒→赤、または赤→黒といったモーション(時間は4フレーム)で行うという作業が大量に発生。
最初はとりあえずクラシックトゥイーンにショートカットを割り当ててシコシコやっていたけど、よく考えたら、全部コマンド化して一括に実行すればいいんじゃね?と思い、試してみました。

まずはヒストリパネルから、必要な手順を選んでjsfl化しようと思ったのですが・・・
フレームの移動の部分をjsfl化してくれないので無理ということに。
※ヒストリパネルからコマンド作成は、↓の記事が参考になりました。
Mattari Blog:jsflのすすめ

じゃあ、足りない部分は自分でjsfl書いてみる!ということでjsfl初チャレンジ!!

で、できたのがこちら。

// 赤になる
// This command was recorded by Adobe Flash CS4.

//タイムラインを変数で保持
var path = fl.getDocumentDOM().getTimeline();

// インスタンスの濃淡: '#ff0000', 100%
fl.getDocumentDOM().setInstanceTint('#ff0000', 100);

//フレーム数を取得
var fr4 = path.currentFrame-4;

//指定したフレームをキーフレームに変換
path.convertToKeyframes(fr4);

//指定したフレーム数をモーショントゥイーンに変換
path.createMotionTween(fr4);
// 黒になる
// This command was recorded by Adobe Flash CS4.

var path = fl.getDocumentDOM().getTimeline();

// インスタンスプロパティ: colorMode, none
fl.getDocumentDOM().setElementProperty('colorMode', 'none');

//フレーム数を取得
var fr4 = path.currentFrame-4;

//指定したフレームをキーフレームに変換
path.convertToKeyframes(fr4);

//指定したフレーム数をモーショントゥイーンに変換
path.createMotionTween(fr4);

使い方としては、トゥイーンを終了させたい位置にキーフレームを打って、上記のコマンドを実行すると、
それぞれ4個前のフレームから始まるモーショントゥイーンが設定されます。

本当は、最初のキーフレームを打つ部分もjsflにまとめたかったのだけど、その処理を入れると色のプロパティを変更する処理が実行されなかったのよね・・・
なんかできそうな気はするけど、こんどえらい人に聞いてみよう。