2007年12月13日

AS3.0がきた

超遅ればせながらやっとAS3.0をいじっています。
なんだか自由にのびのびやりなさいという教育方針の先生が急にいなくなり、正反対の超厳しい先生がいきなりやってきたという感じです。厳しい指摘にヒーヒー言わされております。

躓いたところをまとめて行きます。
MC「square」をx100まで移動したら削除するasを書きました。
AS2.0ではこう


function layout(){
attachMovie("square","sq1",1);
_root.onEnterFrame = moveX;
}

function moveX(){
sq1._x += 1;
if(sq1._x > 100){
removeMovieClip("sq1");
}
}
layout();

AS3.0ではこう書きました。


import flash.display.*;
import flash.events.*;

var sq1:Sprite;
function layout(){
sq1 = new square();
addChild(sq1);
sq1.addEventListener(Event.ENTER_FRAME,moveX);
}

function moveX(event:Event){
sq1.x += 1;
if(sq1.x > 100){
removeChild(sq1);
}
}
layout();


この中にAS2との変更点がいくつかありますね。おなじみかもですが。
プロパティの_が不要になった。
attachMovieが削除。代わりにaddChildを使用します。
同じくremoveMovieClipが削除。removeChildを使用します。
onEnterFrameなどが使用できなくなりイベントリスナーを使用します。
ライブラリからsquareという名前でリンケージするとnew square()とすれば呼び出せる。
あとこれはFlashCS3でフレームアクションに書いているのでimportでクラスを読み込む必要もないです。(代表的なクラスはすでに読み込まれているから)Flexでの製作のときやクラスを作成するときは必要になります。

これを実行したところコンパイルエラーで
ArgumentError: Error #2025: 指定した DisplayObject は呼び出し元の子でなければなりません。
と出てきてしまう。
これで半日悩みました。
removeChildを実行するときにエラーがでるので重点的に検証していたんですが。
結果これで動きました。


import flash.display.*;
import flash.events.*;

var sq1:Sprite;
function layout(){
sq1 = new square();
addChild(sq1);
sq1.addEventListener(Event.ENTER_FRAME,moveX);
}

function moveX(event:Event){
sq1.x += 1;
if(sq1.x > 100){
removeChild(sq1);
sq1.removeEventListener(Event.ENTER_FRAME,moveX)
}
}
layout();

removeChildでsq1が削除されてsq1に設定したイベントリスナーも削除されるものと思っていましたが、
removeEventListenerでイベントリスナーを削除しないと実行され続けてしまい既に削除されたsq1を
removeChildしていた為にエラーがでていたのでした。removeChild自体は動いていたんですね。
AS2.0ではMC毎にonEnterFrameを持たせてMCを削除したときonEnterFrameも削除されるという組み方をよくやっていたのですが作り方を考えないといけませんかね。

2007年12月14日

AS3.0 event.target

昨日のAS2.0のコードですが


function layout(){
attachMovie("square","sq1",1);
_root.onEnterFrame = moveX;
}
function moveX(){
sq1._x += 1;
if(sq1._x > 100){
removeMovieClip("sq1");
}
}
layout();

こんな書き方の方が望ましいですね。


function layout(){
attachMovie("square","sq1",1);
sq1.onEnterFrame = moveX;
}
function moveX(){
this._x += 1;
if(this._x > 100){
removeMovieClip(this);
}
}
layout();

Mcの参照にthisを使えばmoveX()は使いまわしが効くわけで。
sq1のonEnterFrameにmoveXを当てているのでthis=sq1になりますよね。
ところがAS3.0で同じようにthisを使うと

var sq1:Sprite;
function layout(){
sq1 = new square();
addChild(sq1);
sq1.addEventListener(Event.ENTER_FRAME,moveX);
}
function moveX(event:Event){
this.x += 1;
if(this.x > 100){
removeChild(this);
this.removeEventListener(Event.ENTER_FRAME,moveX)
}
}
layout();

thisがsq1を参照せずMainTimelineを参照します。
AS2.0のようにthisが使えれば凄く便利なんですが…。
結構悩んだんですが、解決しました。
結論からいきます。

var sq1:Sprite;
function layout(){
sq1 = new square();
addChild(sq1);
sq1.addEventListener(Event.ENTER_FRAME,moveX);
}
function moveX(event:Event){
event.target.x += 1;
if(event.target.x > 100){
removeChild(event.target);
event.target.removeEventListener(Event.ENTER_FRAME,moveX)
}
}
layout();

thisの代わりにevent.targetを使えばオッケー。