秘密基地、どこに作った?

Flash ActionScript(アクションスクリプト)の挙動が
思うようにならず困っています。

●使用ツール
 Macromedia Flash MX

●やりたいこと
 ムービークリップ【mc_4_0】【mc_4_1】【mc_4_2】が配置されている。
 各ムービークリップにマウスが乗っているかを毎フレーム判定し、
 乗っていればx/yscaleを1.5倍に、乗っていなければ1倍に戻す。

●現在の処理
 ○メインタイムラインの処理
----------------------------
//最初のシーンを設定
_global.scene = SceneMcSelect

//毎フレーム、シーン関数を呼ぶ
onEnterFrame = function() {
//現在シーンを呼ぶ
eval( _global.scene )();
}
----------------------------

 ○SceneMcSelect関数の定義
----------------------------
function SceneMcSelect(){

for( count = 0 ; count < 3 ; count++ ){

//マウスが乗ったか?
eval("mc_4_" + count).onRollOver = function(){
trace(count);
eval("mc_4_" + count)._xscale = 150;
eval("mc_4_" + count)._yscale = 150;
}
//マウスが離れたか?
eval("mc_4_" + count).onRollOut = function(){
trace(count);
eval("mc_4_" + count)._xscale = 100;
eval("mc_4_" + count)._yscale = 100;
}
}
}
----------------------------

●現在の挙動
 onRollOverやonRollOutの判定は正しく行われているようですが、
 x/yscaleの変更処理が行われません。
 traceでcountの値を確認すると、なぜか【3】になっています。


難しい処理をしているわけではないと思うのですが、
思うとおりの挙動にならず困っています。
何か間違いや見落とし等ございましたら、ご指摘お願いいたします。

A 回答 (2件)

大きな問題点が3点ありますが,


そのうちの2点はとりあえず無視します。


trace(count); の出力結果が 3 になるのは
単純に次のようなスクリプトを書けば理解できると思います。

------------------------------
for (count=0; count<3; count++) {
trace(count);
}
trace(count);
trace(count);
trace(count);
------------------------------

もし for文を動作的に理解するのが難しければ,
while文 にすればわかりやすいかもしれません。
上記 for文 使用のスクリプトと全く同値なものです↓。

------------------------------
count = 0;
while (count<3) {
trace(count);
count++;
}
trace(count);
trace(count);
trace(count);
------------------------------

for文にしても,while文 にしても,
結局 count の値は 3 になってループを抜けます。
したがって次のような出力結果になります↓。

-------
0
1
2
3
3
3
-------

たとえば,
このまま 10秒後 に trace(count); を実行したとしても結果は同じ。
count は 3 のままです。
このまま 1分後 に trace(count); を実行したとしても結果は同じ。
count は 3 のままです。

つまり,
このまま MCにロールオーバーしたときに trace(count); が実行されても結果は同じ。
count は 3 のままです。

したがって,
 eval("mc_4_" + count)._xscale = 150;
はいつ実行しても
 mc_4_3._xscale = 150;
を実行することと同じになります。

というわけで,
単純にこれで良いのではないでしょうか↓。
(#1の方と同じ)

------------------------------
// ユーザ定義関数 SceneMcSelect の定義
function SceneMcSelect() {
for (count=0; count<3; count++) {
//マウスが乗ったら実行する関数を定義
eval("mc_4_"+count).onRollOver = function() {
this._xscale = 150;
this._yscale = 150;
};
//マウスが離れたら実行する関数を定義
eval("mc_4_"+count).onRollOut = function() {
this._xscale = 100;
this._yscale = 100;
};
}
}
// ユーザ定義関数 SceneMcSelect の実行
SceneMcSelect();
------------------------------



本題ではない残りの2つの問題ですが。

> //毎フレーム、シーン関数を呼ぶ
> onEnterFrame = function() {
> //現在シーンを呼ぶ
>   eval( _global.scene )();
> }

なせ onEnterFrame で
毎フレーム毎フレーム onRollOver や onRollOut を定義しなければならないのか,
不可解で意味が理解できません。

上に書いたスクリプトのように SceneMcSelect(); は1回で良いはずです。
何度も定義しなおす必要があることがあったとしても,
その都度ごとに1回で良いはずで,
毎フレーム毎フレーム(コンマ数秒ごとに)再定義し続ける必要は普通ないと思います。

この理由を補足要求しているわけではありませんよ。
本題とは関係の無い部分なのでどうでも良いのですが,
この変な部分は一考の余地があると思いましたので書かせていただきました。



もう1つは eval関数 です。
これを色々なときに使い続けると無事に動作しない場合などが出てきますよ。
eval は主に Flash 4 までで使用されていた古い関数で,Adobe もあまり推奨していません。
完全に非推奨(使用を避ける機能)にはなっていませんが,ほぼ非推奨です。

携帯の Flash Lite 1.x 用のSWFをパブリッシュするなど特別な理由がない限り,
eval は使わずに 配列アクセス演算子 を使うのが一般的です。

Google検索 「配列アクセス演算子 eval」
http://www.google.co.jp/search?hl=ja&q=%E9%85%8D …
    • good
    • 0
この回答へのお礼

ご丁寧にありがとうございます!

>trace(count); の出力結果が 3 になるのは
>単純に次のようなスクリプトを書けば理解できると思います
いやはや、まったくその通りです。失礼いたしました。
MovieClip.onRollOver = function() {}を関数の定義と正しく認識しておらず、
「ユーザ定義関数【SceneMcSelect】が呼び出された時に【MovieClip】の【onRollOver】をチェック」
→「条件を満たしていればその中身を実行」
という処理をするものと勝手に想定していたのが勘違いの元だったようです。

2つ目の問題点としてご指摘いただいたのもまさにこの点が原因でして、
【_global.scene == SceneMcSelect】の時のみ、
常時【onRollOver】【onRollOut】をチェックして処理を実行する、というのが本来やりたかったことです。
(つまり、【_global.scene != SceneMcSelect】のときは【onRollOver】【onRollOut】をチェックをして欲しくない)
これを実現するには、MovieClip.onRollOver = function() {}以外の手段を使うしかないでしょうか?

3つ目のご指摘の、evalに代わる配列アクセス演算子の使用について、大変勉強になりました。
これまでevalを多用していたため、この機会に差し替えたいと思います。

重ね重ね、ご丁寧なご解答ありがとうございます!

お礼日時:2009/03/25 01:22

function の中身は、


eval("mc_4_" + count)._xscale = 150;
でなくて、this._xscale = 150; じゃないでしょか?
ロールオーバーした時点ではcountは生きてないと思う。
    • good
    • 0
この回答へのお礼

お早い回答ありがとうございます!

>eval("mc_4_" + count)._xscale = 150;
>でなくて、this._xscale = 150; じゃないでしょか?
これでうまくいきました! 助かりました。

>ロールオーバーした時点ではcountは生きてないと思う。
まさにその通りですね、お恥ずかしい……。
onRollOver処理を、関数としてではなく
SceneMcSelectが呼び出された際にのみチェックするコマンドとして使おうとしていたのが勘違いの原因だったようです。

ご解答ありがとうございました。

お礼日時:2009/03/25 01:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報