- ベストアンサー
if文での記述の仕方がわからなくて困っています
- winxp flash8です。if文で分岐したいが記述方法が違い、スクリプトが通らない。
- 30個のブロックをfor文で処理し、ボールとブロックが当たったときに条件分岐を行い、処理を行う。
- atariという変数が0の場合はシルエットを取り、それ以外の場合はブロックを非表示にする。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
問題は if文 ではありません。 しかし,かなり古いスクリプトと構造を作られていらっしゃいますね。 Flash Lite 1.x 対応のゲームを作られているとか? とも一瞬思いましたが, Flash Lite 1.x では hitTest が使えませんからそうではありませんよね。 古くからやっている者だとわかります。 スクリプトやムービークリップの構造の原型は Flash5 ですね。 雰囲気は Flash 4 と 5 の中間あたりの感じです。 今の人が見れば 「this._parent.t 何それ?? そんなまわりくどい書き方をする状況がわからない。」 「set って何? クラスファイルの定義でも作成しようとしているの???」 みたいに見えて,状況がわからないと思いますが, Flash 3 ~ Flash 5 では確かにそのようにせざるを得ないことがありました。 またクラスファイルも全く関係ありませんね。 簡単なサンプル例です。 新規ドキュメント作成で次のような3つのムービークリップを作成します。 _root ├ 無名のムービークリップ(スクリプト記述用) ├ ムービークリップ 「tama0」 └ ムービークリップ 「t1」 (ドラッグで動かす) そして, 無名のムービークリップ "自体"には次のように記述。 ----------------------------------- onClipEvent (load) { // ★ 変数 atari0 ~ atari29 の初期化 for (i=0; i<30; i++) { set("atari"+i, 0); } } onClipEvent (enterFrame) { // 30個のブロックをfor文で処理する for (i=0; i<30; i++) { // ボールとブロック t i 番目 が当たったとき if (this._parent.tama0.hitTest(eval("this._parent.t"+i))) { if (eval("atari"+i) == 0) { // ブロック t i を半透明にする eval("this._parent.t"+i)._alpha = 50; // ★↓ココを訂正 set("atari"+i, 1); } else if (eval("atari"+i) == 1) { // ブロックを非表示に eval("this._parent.t"+i)._x = 77; eval("this._parent.t"+i)._y = -100; } } } } ----------------------------------- そして, ムービークリップ 「t1」 (ドラッグで動かす) 自体には次のように記述。 ----------------------------------- on(press){ this.startDrag(); } on(release, releaseOutside){ this.stopDrag(); } ----------------------------------- それでムービープレビューしてみて, 「t1」 をドラッグして,一瞬だけ「tama0」に接触させれば, 「t1」 はちゃんと半透明になって, ずっと接触させ続ければ消えると思います((77,-100)に移動すると思います)。 上のスクリプトにも ★印 を付けていますが, // ★ 変数 atari0 ~ atari29 の初期化 for (i=0; i<30; i++) { set("atari"+i, 0); } このように, 変数 atari0 ~ atari29 に初期値 0 を入れるのを忘れているのではないでしょうか。 また, // ★↓ココを訂正 set("atari"+i, 1); set関数はこのように使わなくてはなりません。 この使い方を間違えていらっしゃるから無事に動作しないのではないでしょうか。 ※ ココで言う set関数 とは クラスファイルで使用する set ステートメント ではなく, set variable ステートメント のことです。 Flash 4 では変数に値を設定するとき 次のように書いていました。 Set Variable:"atari" & i =1 [現在の set("atari"+i, 1); と同じ意味] set variable ステートメントとは,これの ActionScript1.0 での代替版の関数のことです。 こんなの滅多に使いません(普通は使う必要なし)。 Flashドキュメンテーション「set variable ステートメント」 http://livedocs.adobe.com/flash/8_jp/main/00001884.html ====================== 一応,上のように修正&変更させていただきましたが, それにしてもしくみやスクリプトが古すぎますね。 修正した自分でも恥ずかしい状況です。 今や ActionScript3 の時代が来ようとしているのに, その先々代の ActionScript1 でも,このような古いスクリプトは普通用いません。 それに, 上で作成した「無名のムービークリップ」などという妙なものは作成しません。 以下では, 上で書いた内容をさらに普通な方法とスクリプトに書きなおします。 新規ドキュメント作成で次のような2つのムービークリップを作成します。 _root ├ ムービークリップ 「tama0」 └ ムービークリップ 「t1」 (ドラッグで動かす) そして, _root のフレームには次のように記述。 ----------------------------------- // 変数 atari0 ~ atari29 の初期化 for (i=0; i<30; i++) { _root["atari"+i] = 0; } _root.onEnterFrame = function() { // 30個のブロックをfor文で処理する for (i=0; i<30; i++) { // ボールとブロック t i 番目 が当たったとき if (_root.tama0.hitTest(_root["t"+i])) { if (_root["atari"+i] == 0) { // ブロック t i を半透明にする _root["t"+i]._alpha = 50; _root["atari"+i] = 1; } else if (_root["atari"+i] == 1) { // ブロックを非表示に (★普通は _visible を使わない?) _root["t"+i]._x = 77; _root["t"+i]._y = -100; } } } }; ----------------------------------- そして, ムービークリップ 「t1」 (ドラッグで動かす) 自体には次のように記述。 (これは上と同じで変更ありません。) ----------------------------------- on(press){ this.startDrag(); } on(release, releaseOutside){ this.stopDrag(); } ----------------------------------- そして,ムービープレビューしてみて, 「t1」 をドラッグして,一瞬だけ「tama0」に接触させてみて検証します。 だいたいこれが, 普通の ActionScript1.0 の書き方です。 evalは使用しません。 evalを使用するから,等式(代入式)の左辺に持って来れなくなって, set関数などというさらに妙なものを出没させなければならなります。 普通は eval ではなく,配列アクセス演算子 [ ] を使用します。 eval の場合は,まとめて1つのパスを示しますが, 配列アクセス演算子を使うと [ ] の中は1階層のみを示します。 階層までもが動的に変動する処理ではないので,配列アクセス演算子で十分です。 また, 色々なものを監視したり,色々なものを総合的に動かすのに, Flash 5 までは 「ぜんぜん関係のないムービークリップを作成する」 必要がありました。 ですから,兄弟階層から兄弟階層に司令を出すというような妙なことをしなければならないこともありましたが, FlashMX以降はその必要はありません。 「ぜんぜん関係のないムービークリップを作成する」という考え方自体は, 「オブジェクトを見える形で用意する」ということとなって, 例えば Mouseオブジェクト や Keyオブジェクト がイメージしやすくなるので, 知っていても全く損ではない方法ですが,実際には使うことは普通ありません(Flash Lite 1.x を除く)。 ====================== あと, バラバラと沢山の変数を作成するのは私は嫌ですし, その変数を操作するときもバラバラの変数では操作しにくいので, 私なら,変数 atari0 ~ atari29 のようなものは作成せずに,1つの配列として管理します。 それにその変数群の作成は,配列をエミュレートしていることと同じだと思います。 Flashドキュメンテーション 「eval 関数」 http://livedocs.adobe.com/flash/8_jp/main/00001726.html それと, 場合によるので何とも言えませんが, // ブロックを非表示に (★普通は _visible を使わない?) _root["t"+i]._x = 77; _root["t"+i]._y = -100; この部分も MC._visible = false にするか, もしくは動的に作成した t0 ~ t29 であれば, MC.removeMovieClip() で全く削除すると思います。 ---例----------------------------- // 配列 atariArr の作成 atariArr = new Array(); // atariArr の [0] ~ [29] 要素の初期化 for (i=0; i<30; i++) { atariArr[i] = 0; } _root.onEnterFrame = function() { // 30個のブロックをfor文で処理する for (i=0; i<30; i++) { // ボールとブロック t i 番目 が当たったとき if (_root.tama0.hitTest(_root["t"+i])) { if (atariArr[i] == 0) { // ブロック t i を半透明にする _root["t"+i]._alpha = 50; atariArr[i] = 1; } else if (atariArr[i] == 1) { // ブロックを非表示に _root["t"+i]._visible = false; } } } }; ---------------------------------- 長々と書きましたが, とりあえず 最初に書いたような書き方 でやってみてください。 set関数の使い方がおかしいという部分です。 そしてその点がクリアされて,もし余裕があれば, もっとスクリプトや構造を今風(と言っても上で私が書いたものでも5年くらい前の書き方でこれでも古いです)な構造やスクリプトにしてみてください。 eval や set など, 今やほとんど見ることがなく参考サイトも少ないようなスクリプトでは使い方事例も見つからないと思います。 もっと今風(と言ってもせめて5年くらい前の書き方)にすれば,もっと楽に作成できますし,エラーも起こりにくくなります。
その他の回答 (2)
- BlurFiltan
- ベストアンサー率91% (1611/1754)
#2です > 絶対パスを使うのが一般的なのでしょうか? それは場合によるので一概には言えませんね。 > 親のswfに読み込んだ時に > 階層がおかしくなっていまったことがあったので そういう場合は, ムービークリップの _lockrootプロパティ(一応プロパティらしいです)を使えば良いと思います。 a_mc に外部 SWF を読み込んだ場合, a_mc._lockroot = true; と書くかもしくは, 読み込まれる外部 SWF のフレーム1などに this._lockroot = true; と書くと, その SWF 内で _root がロックされるので,_root が親SWFに移動しなくなります。 プロパティを設定するタイミングなどが色々ややこしいので, 普通は,読み込まれる外部 SWF のフレーム1の方に, this._lockroot = true; を書くのが一般的なようです。 読み込まれる側の SWF を単体で動作させるときにすでに書いてあっても,何の支障もありません。 FlashMX2004(Flash Player 7)以上。
お礼
ありがとうございました。 _lockrootプロパティの件は、目からうろこです。 勉強不足では、ありますが。 描きたい、作りたいから始まってしまうので、その都度、本を開きながら探しながら何とかしてしまっていました。 いろいろとわかりやすく丁寧なご回答、ありがとうございました。 独学で突き進んでいる身には、大変ありがたい場です。 ご親切を感謝します。
- zari514
- ベストアンサー率48% (26/54)
...状況が分かりません。 ステージにどんな要素があって、どこにスクリプトが書かれてて、 何をどうしたくて、どううまくいかないのかを、ご説明ください。
補足
説明が足りなくてすみません。ブロック崩しゲームです。 ステージに4種のブロックが30個ランダムに並べています。 このブロックがはじめはシルエットになっていて、1回目ヒットで シルエットがなくなり2回目でブロックが消えるということをしたいのです。このスクリプトが書かれているのは、ステージ外に配置したブロックと玉のヒットテストを管理するコントロールmcです。 ヒットが1回目か2回目かを判断させて、その場合の処理を入れようとしたのですが、if文が通らなくてブロックにヒットテストされません。 入れ方なのか、書き方なのかわからない状況です。上記はスクリプトの一部ですが、trace((eval ("atari" + i)));で結果が出てこないのでこれがいけないのかと思っているところです。よろしく、お願いします。
補足
丁寧なご回答、ありがとうございました。 悩んでいるうちに古いスクリプトをひっぱりだしてきたら何とかなってそのうちにごちゃごちゃになっていました。 いつも行き当たりばったりで作っていて悲しくなることも。 ブロックを消すのにvisibleを使ったら、見た目は消えたのに1度玉をミスして初期値にもどった時、当たり反応があったので力技で外に飛ばしてしまいました。また、MC.removeMovieClip()はmcがスクリプトでできたものではないので使えませんでした。配列はいつも苦手でどこに[]を入れたらいいのかわからなくなりますが、使うようにします。 階層の書き方ですが、絶対パスを使うのが一般的なのでしょうか?親のswfに読み込んだ時に階層がおかしくなっていまったことがあったので相対パスで書くのがいいのかと思いました。とにかく、ありがとうございました。今風に書けるようにがんばってみます。