問答収集 カテゴリ:Flashプログラミング
現在のスレッド一覧 / 新規に質問を投稿
レス数:9 / 状態:解決済み / No:108 / ATOM
1 日付:2013/01/12(土)12:31:34 ID:4hAxJ8O5MGOq
ムービークリップ内で#initclip ~ #endinitclipを用いて一度だけ変数を初期化する・・・
というのをAS3で再現するのに良い方法はないでしょうか?

ムービークリップ内でローカル変数Aを宣言して、変数Aの値によってそのムービークリップの対応する特定のフレームに移動するようにしたいのですが、
フレーム1に戻ってきたときに『var A:int』が実行されてローカル変数Aの値が初期化されてしまい、毎回同じフレームに飛んでしまいます。
グローバル変数等用いずに、そのムービークリップだけでこの動作を完結させたいのですが。

よろしくお願いします。
2 日付:2013/01/12(土)15:46:02 ID:uqGvQ4UrzKin
ActionScript 2.0 と 3.0 の相違一覧です。
http://www.adobe.com/devnet-archive/actionscript/as3_migration_table.html
http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/migration.html

#initclip ディレクティブは廃止されていますね。
3 日付:2013/01/12(土)15:46:16 ID:uqGvQ4UrzKin
クラスを定義して、コンストラクタ内に初期化したい処理を記述すると
グローバル変数等を使わずに初期化できると思います。

また、タイムラインだけで実行したい場合、
チェック用の変数を1つ用意すれば実現できるのではないでしょうか。

// 変数宣言テスト
var aaa:int;
var bbb:String;


// 初期化用の処理
var initialized:Boolean;
if(!initialized){
initialized = true;

// 初期化したい処理 ----------
aaa = 0;
bbb = "初期化";
// 初期化したい処理 ----------

}


// 出力テスト
trace(aaa);
trace(bbb);

// 変更テスト
aaa += 1;
bbb = "変更";
4 日付:2013/01/12(土)23:07:23 ID:4hAxJ8O5MGOq
>>2-3
ありがとうございます。
1度だけ初期化するという動作になりました。
ただ、他の原因でやりたかった事が実現できませんでしたorz

FlashCS6というソフトを使っているのですが、シンボル化したキャラクターがライブラリに登録されていて、それをいくつも画面上に配置しています。
同じキャラクターの複製が簡単に沢山画面上に配置できたのですが、それぞれのキャラクターが持っているローカル変数をグローバル変数に渡せない(方法がわからない)ので、ローカル変数だけで完結できるよう上記のような処理方法を選びました。

やりたかった事は、複製されたそれぞれのキャラクターの現在の状態をローカル変数に保存しておいて、画面を切り替えて他の処理をした後、またもとの画面に戻ってきたときにそれぞれのキャラクターが画面切り替え前の状態に戻るようすることでした。
ですが、上記方法だと画面が切り替わって戻ってきたときに、再度各キャラクターが呼び出されたものとして、またローカル変数の宣言がされてしまい、初期状態に戻ってしまいました。

やはり、グローバル変数を用意しておいて画面が切り替わって戻ってきたときにその変数の値によって状態を変化させなければならないんでしょうか・・・
しかし、ローカル変数じゃなくてグローバル変数を直接弄ると、複製された各キャラクターは全員同じグローバル変数を弄ろうとして、最後に値を入れたキャラの状態に統一されてしまうんですよね。
(ムービークリップ内に記述されているアクションスクリプトも複製されたものなので皆同じになっていますから。)

ライブラリに登録されているキャラクターのムービークリップを配置する数だけ複製して、各ムービークリップ内で個別にグローバル変数に値を入れるようにしてやれば実現できそうなんですが、
配置されるキャラ全部がまったく別のシンボル(?という表現が正しいのかわかりませんが・・・)としてメモリ沢山使われそうで・・・
同じシンボルの複製の方がメモリ消費量は少なくて済むような事書かれていたきがして。

う~ん、基礎がわかってないとやっぱり難しいですね。
5 日付:2013/01/13(日)22:29:55 ID:uqGvQ4UrzKin
>それぞれのキャラクターが持っているローカル変数をグローバル変数に渡せない(方法がわからない)

ルートとなるタイムラインにアクセスする方法です。

http://mcs.jp/flash/102
http://hakuhin.jp/as3/container.html#CONTAINER_00


>画面が切り替わって戻ってきたときに、再度各キャラクターが呼び出されたものとして、またローカル変数の宣言がされてしまい、初期状態に戻ってしまいました。

シンボルを静的に配置した場合ですが、
タイムラインの再生位置が、シンボルを配置したキーフレーム範囲内に入ると、インスタンスが生成されます。
タイムラインの再生位置が、キーフレーム範囲外に移動すると、インスタンスはリムーブされます。

そして再度、タイムラインの再生位置がキーフレーム範囲内に入ると、新規にインスタンスが作られます。
始めにインスタンス化されたオブジェクトが生存し続けているのではなく、
1つ目のインスタンスは除外され、2つ目のインスタンスが作られます。


余談ですが、タイムラインアニメーションを利用している場合は、厄介です。

同じシンボルを使って、キーフレームを連続で配置するわけですが、
見た目には、同一のオブジェクトが表示され続けているので、同一のインスタンスが生存し続けるのだろうと予想してしまいますが、
実際は、必ずしも同一のインスタンスが生存し続けるとは限りません。

同一のインスタンスが生存し続ける場合もあれば、
キーフレームを越えるたびにリムーブされ、新規にインスタンスが作り直されている場合もあります。

どちらになるかは、コンパイル時の最適化により変化します。
6 日付:2013/01/13(日)22:30:06 ID:uqGvQ4UrzKin
>やはり、グローバル変数を用意しておいて画面が切り替わって戻ってきたときにその変数の値によって状態を変化させなければならないんでしょうか・・・
>しかし、ローカル変数じゃなくてグローバル変数を直接弄ると、複製された各キャラクターは全員同じグローバル変数を弄ろうとして、最後に値を入れたキャラの状態に統一されてしまうんですよね。
>(ムービークリップ内に記述されているアクションスクリプトも複製されたものなので皆同じになっていますから。)

キャラクター内部から、外部の情報に直接アクセスする事はあまりオススメしません。

キャラクター設計者は、状態を復元するための、値のインポート機能と、値のエクスポート機能のみを供給します。
キャラクター利用者は、どこに保存するかを自由に決めれるため、汎用性が高くなります。



>ライブラリに登録されているキャラクターのムービークリップを配置する数だけ複製して、各ムービークリップ内で個別にグローバル変数に値を入れるようにしてやれば実現できそうなんですが、
>配置されるキャラ全部がまったく別のシンボル(?という表現が正しいのかわかりませんが・・・)としてメモリ沢山使われそうで・・・
>同じシンボルの複製の方がメモリ消費量は少なくて済むような事書かれていたきがして。

キャラクター設計者は、キャラクター利用者に一方的に利用される機能を供給します。

しかし、キャラクター内部から外部の情報にアクセスしてしまうと、一方的ではない依存関係が発生します。
依存関係が発生すると、専用の処理となり、利用場面が限定されます。
利用場面が限定されたので、シンボルを複数用意しなければ対応できない状態に陥ります。



キャラクター利用者が、
自前でキャラクターをインスタンス化した場合は、このような流れになると思います。
──────────────────────────────────
利用者が、キャラクターをインスタンス化する

利用者は、キャラクターをステージに配置する


利用者は、キャラクターに情報をセットし、状態を復元する

利用者は、キャラクターを制御する

利用者は、キャラクターから状態の情報を取得する



利用者は、キャラクターをステージからリムーブする
──────────────────────────────────



今回は、シンボルを静的に配置しているため、システムが自動的にインスタンスを生成します。

インスタンス化されるタイミングは、タイムラインを動かして、画面を切り替えたときです。
このタイミングで、システムが生成したインスタンスを取得すれば、制御が可能となります。
──────────────────────────────────
タイムラインを動かして、画面を切り替える

システムが、自動的にキャラクターをインスタンス化する。

利用者は、システムが生成したインスタンスを取得する。



利用者は、キャラクターに情報をセットし、状態を復元する

利用者は、キャラクターを制御する

利用者は、キャラクターから状態の情報を取得する



タイムラインを動かして、画面を切り替える

システムが、自動的にキャラクターを破棄する
──────────────────────────────────

インスタンスを取得する方法です。
http://hakuhin.jp/as3/container.html#CONTAINER_04
7 日付:2013/01/13(日)22:53:31 ID:uqGvQ4UrzKin
シンボルを複数用意しなければならない問題を回避して、
キャラクター内部から、グローバルな変数にアクセスしたい場合は、
「インスタンス名」を識別情報として利用するといいと思います。

シンボルを3個配置して、インスタンス名をそれぞれ、
"my_chara_a" , "my_chara_b" , "my_chara_c" と名付けます。

───────────────────────────
// ルートのタイムラインに記述
var character_dictionary:Object = new Object();
character_dictionary["my_chara_a"] = "テスト1";
character_dictionary["my_chara_b"] = "テスト2";
character_dictionary["my_chara_c"] = "テスト3";


───────────────────────────
// キャラクター用ムービークリップのタイムラインに記述
var root_obj : Object = this.root as Object;
trace(root_obj.character_dictionary[this.name]);
8 日付:2013/01/18(金)22:51:04 ID:4hAxJ8O5MGOq
ありがとうございます!
考えていた通りの動作を実現することができました!

インスタンス名を変数に付記して使えれば・・・と考えていたのですが、上記方法でインスタンス名を変数に付記して、各シンボルでそれぞれのインスタンス名を変数に付記させることができました。
シーンを切り替えてもばっちり切り替え前の状態を残しておく事ができるようになりました。
キーフレームの範囲外になるとインスタンスがリムーブされるという仕組みも知る事ができました。
本当にありがとうございました。

もう一つ勉強になったのは、アクションスクリプトは必ずしも記述した順番通りに処理されるわけではない(?)という事です。
上記方法により保存しておいたグローバル変数の値によってフレーム移動するように記述したのですが

if(変数が1のとき){
 gotoAndPlay(2);
}else if(変数が2のとき){
 gotoAndPlay(3);
}else if(
 以降・・・・・
}else{
 //何もしない
}

と、書いた後に

var A;
A = Math.floor(Math.random() * 300);
if (A == 5){
    gotoAndPlay(2);
}else{
    gotoAndPlay(1);
}

と書いて、変数が初期の0の間は何度もフレーム1を繰り返してると自然とフレーム2に飛ぶようにしました。
が、結果として、この書き方だと確かにグローバル変数は各状態に応じて書き換わっているのにもかかわらず、上のif文による判定を行わずに先に下のループを繰り返してしまい、各フレームに飛ばずにいずれフレーム2に飛ぶという動作を繰り返してしまいました。
コレに気付かずに、どうして変数は変わっているのに飛ばないのだろう、変数が数値じゃなくて文字列になっているんだろうか?など考えて試行錯誤してました。

結局、下のループ処理をif文の判定の最後のelse(何もしないとしていたところ)に入れてやるとちゃんとif文による数値判定を行って各フレームに飛ぶようになりました。

また、アドバイスをいただきに来ると思いますが、その時はまたよろしくお願いいたします。
9 名前:状態変更 日付:2013/01/18(金)22:51:58 ID:4hAxJ8O5MGOq
この質問の状態を『解決』に変更しました。
このスレッドについて
質問の状態 :
解決済み
投稿開始日 :
2013/01/12(土)12:31:34
投稿終了日 :
2013/01/25(金)22:52:47
投稿者 :
レス総数 :
9
スレッド番号 :
108
MondoCollectionSystem ver.0x00020000 by Hakuhin