as2: 2008年1月アーカイブ

Yoropan@Flaさんのブログ記事にコメントしたら失敗してしまいました。
http://yoropan.no.coocan.jp/wp/index.php/archives/85#comment-31

ここにコメントで書こうとしたソースを掲載しておきます。

Yoropan@Flaの筆者さん、すいませんでした。

var arr:Array = [0,1,2];

for(var i=0; i<arr.length; i++){
  var names="hoge"+i;
  var box_mc = this.createEmptyMovieClip(names,i)
  box_mc.i=i;
  box_mc.onRelease=function(){
    box_mc.name=arr[this.i];
    trace("--release event");
    trace("box_mc.name = "+box_mc.name);
    trace("hoge0.name = "+hoge0.name);
    trace("hoge1.name = "+hoge1.name);
    trace("hoge2.name = "+hoge2.name);
    trace("box_mc = "+box_mc);
    trace("this = "+this);
    trace("");
  }
  fillRect( box_mc );
  box_mc._x = i*110;
}
trace([i,box_mc]);

function fillRect( mc )
{
  var x = 100;
  mc.beginFill(0,100);
  mc.moveTo(0,0); mc.lineTo(x,0);
  mc.lineTo(x,x); mc.lineTo(0,x);
}

はじめてトラックバックという機能を使ってみます。緊張の一瞬です。

trick7さんがblogに「画像をロードしたMC 上に attachMovie できない」という記事を書かれてまして、これってよくいろいろと聞かれるので書いておこうと思いました。

まずテスト用に以下の図のような構成の"main.swf"と"sub.swf"というファイルを用意しました。


"sub.swf"のルートの1フレーム目には
trace(this);
とだけ書かれています。
あと、ムービークリップ「imageMC」を配置、そのなかに直接画像を配置しています。

で、"main.swf"にはリンケージ設定をした「attachMC」がライブラリに入った状態で、以下のスクリプトをルートに書いておきます。
import flash.display.BitmapData;

var loadMC:MovieClip = this.createEmptyMovieClip("loadMC",10);
var bmp1:BitmapData = new BitmapData(100,100,true,0);
var bmp2:BitmapData = new BitmapData(100,100,true,0);
var draw1:MovieClip = this.createEmptyMovieClip("draw_1",20);
var draw2:MovieClip = this.createEmptyMovieClip("draw_2",30);
loadMC._y = 120;
draw2._x = 120;

var loader:MovieClipLoader = new MovieClipLoader();
var listener = { onLoadComplete:function(){ 
    trace(loadMC.imageMC); // output : undefined
	
    loadMC.attachMovie( "attachMC", "attachMC" , 10 );
    bmp1.draw( loadMC ); // 描画されない
    draw1.attachBitmap( bmp1, 10, "auto", true );
    
	loadMC.onEnterFrame=function(){
      trace(mc.imageMC); // output : _level0.loadSWF.imageMC
      
	  bmp2.draw( loadMC ); // 描画される
      draw2.attachBitmap( bmp2, 10, "auto", true );
      delete this.onEnterFrame;
    } 
  }};
loader.addListener( listener );
loader.loadClip( "sub.swf" , loadMC );
結果は以下のようになります。

出力結果
undefined
_level0.loadMC.imageMC
_level0.loadMC
「出力結果」の3行目が"child.swf"の「trace(this);」の出力になります。

まず、AS2では読み込み元(この場合は"loadMC")が"sub.swf"のルートになります。(画像の場合も同様かと思います)
読み込みが完了した後、15行目の「loadMC.attachMovie(~」でattachしようとしているのですが、この時"loadMC"は"sub.swf"のルートになっているので、"sub.swf"のルートに attachMovie しようとしていることになります。
AS2では外部読み込みしたSWFに対してattachで配置することができません。(逆も同じです。)
なのでこの場合も配置することができないのです。


あと、合わせてよく聞かれるのが BitmapData の draw とかその辺です。というかイベントのタイミングの話になるのですが。
なので一緒にテストしてみました。
最初の図と見比べていただくと"draw1"の箇所が表示されていないのが分かります。
スクリプトでいうところの16、17行目の箇所です。
これは、"onLoadComplete"イベントが発生した時点では、読み込みは完了しているが画面上に書き出されていないことをあらわしています。
まだ書き出されていないので、13行目の参照も、結果は「undefined」になってしまいます。

そこで一連の処理が終わって、描画処理も終わった後で"draw"を実行するために"onEnterFrame"を使っています。
"onEnterFrame"は現在のフレームの処理がすべて終わった後、次のフレームに移った瞬間に実行されるので、おそらく読み込みが完了してから最短で"draw"する方法じゃないかと思います。
それが20行目から24行目になります。1回実行したらこの処理はもういらないので"delete"で削除してます。


さらについでなのでAS3でも試してみました。
sub.swf
trace(this.name);
main.swf
import flash.display.*;
import flash.net.URLLoader;
import flash.net.URLRequest;

var loadMC:Loader = new Loader();
var bmp1:BitmapData = new BitmapData(100,100,true,0);
var bmp2:BitmapData = new BitmapData(100,100,true,0);
var draw1:Bitmap = new Bitmap( bmp1, "auto", true );
var draw2:Bitmap = new Bitmap( bmp2, "auto", true );
this.addChild(loadMC);
this.addChild(draw1);
this.addChild(draw2);
loadMC.y = 120;
draw2.x = 120;

var request:URLRequest = new URLRequest('sub.swf');
var info = loadMC.contentLoaderInfo;
info.addEventListener( "complete" , listener );
function listener( e ){ 
  trace(loadMC.getChildByName("imageMC")); // null
  trace(loadMC.getChildAt(0).getChildByName("imageMC").name); // imageMC
  
  //mc.addChild( new attachMC() );//Error: Error #2069: Loader クラスは、このメソッドを実装しません。
  loadMC.getChildAt(0).addChild( new attachMC() );
  bmp1.draw( loadMC );
  
  loadMC.addEventListener( "enterFrame" , function(e){
    trace(loadMC.getChildByName("imageMC")); // null
    trace(loadMC.getChildAt(0).getChildByName("imageMC").name); // imageMC
    
    bmp2.draw( loadMC );
    loadMC.removeEventListener( "enterFrame" , arguments.callee );
  } );
}; 
loadMC.load( request );

出力結果
instance4
null
imageMC
null
imageMC
AS3だと外部ファイルにも"new"で配置できるんですね。
AS2と違っているのは"loadMC"が"sub.swf"のルートになるんじゃなくて、"loadMC"の中に"sub.swf"が入るようになったんですね。
あと、この結果からイベントのタイミングが描画されたあとに発生してるのもわかります。

なんか異様に長くなってしもた。
追記:
サンプルのflaファイルをアップしときました
attach_sample.zip
きっと使えば何かと便利なんだろうけど
今まで使ってた自分クラスがなかなか手放せないだけなのかもしれない。

Motionクラス, Easeクラス
import com.seyself.controls.Motion;
import com.seyself.controls.Ease;

var tween = Ease.cubic('out', 12);
var motion = new Motion();

motion.start( mc , { x:100 , y:100 , _rotation:45 } , tween , 0 , 
               { complete:function(e){ trace(e.target) }} );
ちなみに僕はイージングは配列で管理してます。
上記の変数 "tween" は 0 から 1 の配列が入ってます。
実際1つのコンテンツにイージングを何パターンも使うことはあまりなくて
だいたい4種類前後しか使わないので、そのために実行時に何度も
同じ計算をすることもないんじゃないかなあ、と。
そのかわりメモリ食ってるかもしれません。
あんまりその辺、気にしないことにしてます。面倒なので。

Moveクラス

Transクラス

Coloringクラス

Discolorクラス

結局のところ、まとまったドキュメントやら、ソースを見るのが面倒なだけかもしれませんが。

Flash 8 から実装された Matrixクラス や Pointクラスなどが入っている flash.geom パッケージですが、 Wiiとか未だに FLASH Player のバージョンは 7 だとかで、このパッケージは使えないらしい。
これってバージョンアップはしないんでしょうか。

ところで、以前どっかのブログ記事でそんなことを書いている人がいたので試しにバージョン7 でも使えるように 手作り geom パッケージを作ってみました。

一応、概ねカバーできてると思うんだけども一部対応してない箇所があります。
以下対応してない箇所。

Point.add( v:Point ):Point
バージョン7 だと add は演算子扱いされちゃって実装できなかった。
なので、このクラスで addメソッドを使うには以下の方法を取ってください。
point["add"]( pt );//配列アクセスを使う
point.addition( pt );//代替メソッドを用意しています。

Transform.concatenatedMatrix:Matrix
途中で飽きて実装するのが面倒になってしまいました。
誰か気前のいい人が実装してくれたらいいなあと。

Transform.concatenatedColorTransform:ColorTransform
同じく、途中で飽きて実装するのが面倒になってしまいました。
誰か気前のいい人が実装してくれたらいいなあと。

ソースのダウンロードはこちら
20080109_fp7_geom_package.zip

パッケージ名が flash7.geom になってます。(バージョン8と混ざると困ったことになるので)
使いにくかったらパッケージ名は各々で変更してくださいませ。

あと、当然なんですがバージョン7 では MovieClip に transform というプロパティはデフォルトでは付いていないので、 最初に対象となるムービークリップに対して new しないといけません。
import flash7.geom.Transform;
var trans:Transform = new Transform( targetMC );
上記の対応してない箇所以外はバージョン8 のクラスと同じです。
コメントはほとんど書いてないので、使い方の分からないところは、製品のヘルプか、LiveDocsを参照してください。

ご使用、改変はご自由に。
あんましデバッグとかしてないので、バグがあったらすいません。
このクラスの利用はあくまで自己責任にてお願いします。

Matrix の値から拡大縮小、回転、位置の値を取る計算式。
import flash.geom.Matrix;
var mat:Matrix = new Matrix();
mat.createBox( 12 , 36 , Math.PI/4 , 10, 50 );
trace( mat );
trace( getParam( mat ) );

function getParam( m:Matrix ):Object
{
  var totalScale:Number = m.a * m.d - m.b * m.c;
  var sx:Number = Math.sqrt(m.a * m.a + m.c * m.c);
  var sy:Number = totalScale / sx;
  var angle:Number = Math.acos( m.a / sx );
  var obj = { scaleX:sx , scaleY:sy, rotation:angle, x:m.tx, y:m.ty };
  obj.toString = function()
  {
    return "(scaleX="+this.scaleX+" , scaleY="+this.scaleY+
			 ", rotation="+this.rotation+", x="+this.x+", y="+this.y+")";
  }
  return obj;
}