« 他ブログ紹介(BlogPet) « » 過保護の定義 »

2006年05月22日

 returnとフレームアクションの実行順序このエントリーを含むはてなブックマーク

(・∀・)イイ・アクセスさんから
FN0605002 - returnステートメント - Flash : テクニカルノート
へリンクが貼られていました。
っていうか何故今!?とか思っているのですが。
これに関連してフレームでのASの記述について色々思い出したので書きます。
特にAS2.0やら3.0やらバリバリなJava・CプログラマにはFlash独特の処理があるタイムラインを嫌う傾向があって、その嫌われる原因の特殊な処理あたりを紹介します。
Flash初心者の人もfunctionの実行順序なんか必見。

レイヤー分けされたASの処理

有名なところから。
同じフレームの別レイヤーに記述されたASは上から全て繋げられることになります。
昔はこれを利用して目的ごとにレイヤー分けしてたんですが、最近はやめました。
検索しにくいってのが一番ネックです。
アクションウインドウに長々と書かなければいけない場合は、includeを使って外部ファイルに記述しちゃうべきだと思います。

実行順序が変化するAS・function

今回のメインのお話です。
タイムラインのASは実行順序が自動的に変化するものがあります。
初心者の方はfunctionがどういう条件で実行されるの?と不思議に思っている人がいます。
同じフレームにあればいいのか、命令前に定義されていればいいのか・・・。
先にこれを答えておくのですが、functionは変数と同じ扱いです。
定義された場所以降使用することができ、何回も定義されるとそのたびに上書きされます。
、と聞いて、あれれ?と思った人がいるでしょう。

testA();
function testA() {
	  trace("A");
}

こんな処理の場合、testAが定義される前に、呼び出せて「A」と表示されるのです。
でも、関数の宣言ってもう1個ありましたよね?○○=function(){~~}ってやつ。
ちょっとこれでテストしてみましょう。

testA();
testA = function () {
	trace("A");
}

なんと、これでは「A」と表示されない、つまり関数が呼び出せていないのです。
えー、なんでー?。
次にこんなことをしてみましょう。

testA = function () {
	trace("A-1");
};
function testA() {
	trace("A-2");
}
testA();

予想は?2番目の関数宣言が上書きされて「A-2」となるでしょうか?
正解は「A-1」が表示されます。

function testA() {
	trace("A-2");
}
testA = function () {
	trace("A-1");
};
testA();

逆にしてみても結果は同じ、「A-1」です。

何がおきているのかというと、「function なんとか~」 というASは、自動的にそのフレームの一番最初に移動しているのです。
つまり、同じフレームであれば宣言する前に関数を使えるのは、実は勝手にその前に宣言されちゃっているのです。
移動はレイヤーも飛び越え、同じフレームの最初で宣言されるようです。
これを知ると色々と宣言上の問題を回避できます。
関数の中で関数の宣言をしてわけわからないことになってた人がいますがwこれを理解できれば対処できるはずです。

ちなみに移動するfunctionは平文にあるものに限ります。

testA();
if (true) {
	function testA() {
		trace("A");
	}
}

これは実行されません。

実行順序が変化するAS・gotoAndPlay()

Flash職人が2・3番目によく使うであろうgotoAndPlay()なのですが、実はこれにも実行順序に注意が必要な面があります。
まず、有名な例ですがフレームの描画タイミングを1個スキップします。

// 1フレーム目
trace("1");
// 2フレーム目
gotoAndPlay(1);

この場合、1フレーム目が途切れることなく実行されます。
1フレーム目→画面描画→2フレーム目→1フレーム目→画面描画・・・
というわけですね、2フレーム目は描画されないわけです。
ですので、もし

// 1フレーム目
gotoAndPlay(2);
// 2フレーム目
gotoAndPlay(1);

こう記述すると画面描画されることなくずっと1フレーム目と2フレーム目の無限ループが発生してFlashがフリーズします(マジです、実験するときは気をつけましょう)

さて、ここからが本題。

// 1フレーム目
trace("1-1");
gotoAndPlay(2);
trace("1-2");
// 2フレーム目
trace("2")
stop();

さあ、何が表示されるでしょうか。
「1-1」→「2」となって、「1-2」は消えてしまう?
それとも「1-1」→「2」→「1-2」という風に、残りもちゃんと実行される?
正解は「1-1」→「1-2」→「2」です。
なんで??
じゃあこれは?

// 1フレーム目
trace("1-1");
gotoAndPlay(2);
trace("1-2");
gotoAndPlay(3);
trace("1-3");
// 2フレーム目
trace("2")
stop();
// 3フレーム目
trace("3")
stop();

正解を書いてしまえば、「1-1」→「1-2」→「1-3」→「2」→「3」です
gotoAndPlay()やgotoAndStop()は呼ばれても直ちに処理されず、フレームの処理が全て終了してから順に実行されます。
ですから同じフレームに2個以上のgotoAndPlay()やgotoAndStop()がある場合は気をつけましょう。
とっても処理がややこしいのですが、次のreturn文を使用することで制御が楽になることがあります。

returnのフレームでの効能

なんとフレームアクションでいきなりreturn文を記述することができます。

trace("A");
return;
trace("B");

この例では「A」しか表示されなくなります。
returnはフレームで使用すると、そのフレームのASをそこで強制終了にします。
この強制終了はさっきのgotoAndPlay()に効果があります。

// 1フレーム目
trace("1-1");
gotoAndPlay(2);
return;
trace("1-2");
gotoAndPlay(3);
trace("1-3");
// 2フレーム目
trace("2")
stop();
// 3フレーム目
trace("3")
stop();

この場合、表示は「1-1」→「2」です。
gotoAndPlay(2)を記述した後のreturnでフレームが終わったことにされ、gotoAndPlay(2)が直ちに実行されます。
残りの処理は全て切り捨てられるわけです。

ちなみに

testA();
return;
function testA() {
	  trace("A");
}

これは「A」が表示されます。
functionはreturnよりも上へ移動してしまうために、returnの影響を受けません。

コメント

76   投稿者: 日立製作所 ◆2TENKK.nkY (2006年05月24日 22:25)

gotoandplayで直ちにフレームが変わったら関数で呼び出しするとたぶんオカシなことになるので1frameが終了した時点で実行されるんじゃないかな。
それに、描画するにあったても無理矢理ASの実行速度に併せて描画するなんて到底不可能だし。(一般的な言語みたいにバッファに描画->画面に反映->画面バッファクリアの繰り返しすれば問題ない?)


プログラムが慣れてくると実行順序が不明瞭なのは非常にきつい物がある。
初心者がゲームを作る場合なんかFlashのエセマルチスレッドっぽい処理は非常に重宝なのだが、ある程度プログラムに慣れてきたからいざ改良しようと言うことになると、タイムラインベースで作られたゲームプログラムの場合、非常に保守性、再利用性に傍るから最悪1から作り直さなけりゃならない場合もある。


と、授業かなんかで組み込みマイコン組んでいて思った。
とりあえずシーケンサーは実行順序が不明瞭で嫌い。

77   投稿者: しっぽ (2006年05月25日 12:20)

>プログラムが慣れてくると実行順序が不明瞭なのは非常にきつい物がある。
これは激しく同意です。
僕はルートに1つだけenterFrameCastというMCをつくり、
そこからメインの関数を呼び出して、
その関数がすべての動作を管轄するようにして
ほかの箇所でEnterFrameを使用しないようにしています。

AS2.0になってかなり改善されましたが
それでもライブラリのMCシンボルをクラスにしたりするとややこしくなりがちです。

1835   投稿者: Leon Mccormick (2007年09月03日 00:16)

renne elasticin paleness favoringly dunker marron manganophyllite tubercularly
http://www.angelfire.com/aoyobu/2.html >am
http://www.angelfire.com/aoyobu/1.html

しっぽのブログ

コメントする

(サーバーが見つかりませんの表示になることがありますが、
正しく投稿されてることが多いです。
落ち着いて確認してみてください。)

はてなブックマーク