• ベストアンサー

FlashLite1.1での当り判定

円と円、矩形と矩形の当たり判定はいろいろなサイト等をめぐり把握できたのですが、 円と矩形の当たり判定の方法がわかりません。 どなたか教えていただけませんか??

質問者が選んだベストアンサー

  • ベストアンサー
noname#35109
noname#35109
回答No.4

#1&3です。 よく考えてみますと,#1の書いたエリアではまだ条件が足りませんでした。  ●●●  ●□●  ●●● という文字の●や□を使うと,#1で書いたようなことになりますが, 実際は, 単純に,□が●の半径分拡大された矩形エリアに●の中心がきた場合に当たったということにはなりませんね。 □が●の半径分拡大された "角丸" 矩形エリアに●の中心がきた場合に当たったということになります。 "角丸" 矩形 の角丸の半径は,● の半径と等しくなりますがこれは難しいです。 とりあえず, #1で回答した内容までを, FlashLite 1.0 ,1.1 で検証するの簡単なサンプルを書きます。 簡単と言っても,PC用Flashのように簡単ではありません。 基礎的な検証をするだけでも,かなり大変です。 まず,ステージ上に用意するインスタンスですが,4つのインスタンスを使うことにします。 1.「指令塔」のはたらきをするムービークリップインスタンス 2.キーイベントを受け取るボタンシンボルのインスタンス 3.矩形のムービークリップ:インスタンス名「blue」 4.円形のムービークリップ:インスタンス名「red」 1の「指令塔」ムービークリップと, 2のキーイベントを受け取るボタンはステージ外の見えないようなところに作成します。 1の「指令塔」ムービークリップの中のタイムラインを2フレームにします。   □ レイヤー 筆・・|○|○| そして,フレーム1に次のように書きます↓。 /////////////////////////////////////////////////////////////// // _root の blue の x座標 を _root の変数 my_x ずつ左右に移動させる setProperty("/blue", _x, getProperty("/blue", _x)+/:my_x); // _root の blue の y座標 を _root の変数 my_y ずつ上下に移動させる setProperty("/blue", _y, getProperty("/blue", _y)+/:my_y); // 検証のため setProperty("/blue", _alpha, 100); // // _root の blue と red の当たり判定 // 各プロパティ値の変数化 rx = getProperty("/red", _x); ry = getProperty("/red", _y); rw = getProperty("/red", _width); bx = getProperty("/blue", _x); by = getProperty("/blue", _y); bw = getProperty("/blue", _width); bh = getProperty("/blue", _height); // if (rx<=bx+bw/2+rw/2) { if (rx>=bx-bw/2-rw/2) { if (ry<=by+bh/2+rw/2) { if (ry>=by-bh/2-rw/2) { // 検証のため setProperty("/blue", _alpha, 50); } } } } /////////////////////////////////////////////////////////////// そして,フレーム2には次のように書きます↓。 ////////////////// gotoAndPlay(1); ////////////////// これで,「指令塔」ムービークリップのタイムラインは, フレーム1 と 2 を繰り返すので, 随時計算処理が行われるようになります。 (gotoAndPlay(1); を書かなければ,フレーム2 の時間がまともにかかるためループ処理が毎フレームにならなくなります。) if文の内容は,#1で説明した通りの内容です(角丸矩形ではなく単なる矩形です)。 また, ムービークリップなどのプロパティ(_x や _y など)を得る場合, そのムービークリップが同じ階層にあれば,ターゲットパスを必要としませんから,  //四角(blue:横移動し円に当たるようにしました)  ax = blue._x; // x 座標  ay = blue._y; // y 座標 のようにしてプロパティを取得しても良いのですが,違う階層になった場合, ターゲットパスには _root. とか this._parent. だとかいうドットシンタックスが使えません。 スラッシュシンタックスを使う必要がでてきます。 そこで,#2の方が回答していらっしゃるように,getProperty("blue",_height); などが必要になります。 本当の本当は,階層が同じでも getProperty("blue",_height); などとする方が良いです。 こちらの方が文法が統一されて混乱はなくなると思います。 また, onEnterFrame や onClipEvent (enterFrame) などありませんから, それを実現できるようにムービークリップでその構造をつくりださなければなりません。 それが フレーム1 と フレーム2 の ムービークリップグルグルループ です。 というか,実は逆で, ムービークリップグルグルループ は, onClipEvent (enterFrame) や onEnterFrame などが無い頃の Flash の普通の使い方です。 このしくみをいちいちムービークリップで作らなければならないのが厄介であったため, ムービークリップに書く onClipEvent (enterFrame) ができたのだと思います。 余計なことを書きましたが,先を続けます。 そして,用意したボタン には次のように書きます↓。 ////////////////////////// on (keyPress "2") { my_x = 0; my_y = -2; } on (keyPress "6") { my_x = 2; my_y = 0; } on (keyPress "8") { my_x = 0; my_y = 2; } on (keyPress "4") { my_x = -2; my_y = 0; } on (keyPress "5") { my_x = 0; my_y = 0; } ////////////////////////// これで,_root の 変数 my_x と my_y の値を変えてやります。 携帯では普通はマウスは使えないので, 2,4,5,6,8キー で矩形の blue を動かす方向を決めるものにしてみました。 これが,今で言う Keyクラス のメソッドの代用ですね。 というか,これまた逆で, ボタンの on (keyPress) の代用が Keyクラス のメソッドなのですが。 これで,適当に配置した blue が動くと同時に, red に当たると hit が出力されるものができます。 これができて, やっと単なる検証ができます。 検証してみると, □と●の当たり判定ではなく, ●を矩形としたものの当たり判定になってしまいます。 というわけです。 以上が, とりあえず,#1で回答した内容までを, FlashLite 1.0 ,1.1 で検証する簡単なサンプルです。 ================ 以下が #1 の解答後, 角丸矩形に関して考え合わせた「指令塔」ムービークリップのタイムライン の フレーム1 のスクリプトです。 ////////////////////////////////////////////////////////////// // _root の blue の x座標 を _root の変数 my_x ずつ左右に移動させる setProperty("/blue", _x, getProperty("/blue", _x)+/:my_x); // _root の blue の y座標 を _root の変数 my_y ずつ上下に移動させる setProperty("/blue", _y, getProperty("/blue", _y)+/:my_y); // // 検証のためアルファを使います setProperty("/blue", _alpha, 100); // // _root の blue と red の当たり判定 // 各プロパティ値の変数化 rx = getProperty("/red", _x); ry = getProperty("/red", _y); rw = getProperty("/red", _width); bx = getProperty("/blue", _x); by = getProperty("/blue", _y); bw = getProperty("/blue", _width); bh = getProperty("/blue", _height); // if (rx<=bx+bw/2+rw/2) { if (rx>=bx-bw/2-rw/2) { if (ry<=by+bh/2+rw/2) { if (ry>=by-bh/2-rw/2) { // 検証のため setProperty("/blue", _alpha, 50); } } } } // 円が矩形の右上コーナーにヒットしたとき以外 a1 = rx-(bx+bw/2); b1 = ry-(by-bh/2); if (a1*a1+b1*b1>=(rw/2)*(rw/2) && rx>=bx+bw/2 && ry<=by-bh/2) { setProperty("/blue", _alpha, 100); } // 円が矩形の右下コーナーにヒットしたとき以外 a2 = rx-(bx+bw/2); b2 = ry-(by+bh/2); if (a2*a2+b2*b2>=(rw/2)*(rw/2) && rx>=bx+bw/2 && ry>=by+bh/2) { setProperty("/blue", _alpha, 100); } // 円が矩形の左下コーナーにヒットしたとき以外 a3 = rx-(bx-bw/2); b3 = ry-(by+bh/2); if (a3*a3+b3*b3>=(rw/2)*(rw/2) && rx<=bx-bw/2 && ry>=by+bh/2) { setProperty("/blue", _alpha, 100); } // 円が矩形の左上コーナーにヒットしたとき以外 a4 = rx-(bx-bw/2); b4 = ry-(by-bh/2); if (a4*a4+b4*b4>=(rw/2)*(rw/2) && rx<=bx-bw/2 && ry<=by-bh/2) { setProperty("/blue", _alpha, 100); } ////////////////////////////////////////////////////////////// やたら,すごい状態になってしまいましたが, なんとか,当たり判定は取れているようです。 私の机上の落書きをお見せすることができたら, 図形的に説明ができるのですが, ここは図形での説明は無理なので,その点は勘弁したください。 数学に強い方だともっとシンプルにできるだろうとは思いますが, 私は数学に弱いので,この辺が限界です。 Flashドキュメンテーション Flash Lite のグローバル関数 > getProperty http://livedocs.adobe.com/flash/8_jp/main/00005199.html Flash Lite のグローバル関数 > setProperty http://livedocs.adobe.com/flash/8_jp/main/00005226.html

lite090
質問者

お礼

ご丁寧にありがとうございました。 なんとか作ることができました^^: やはり、考え方等もっと勉強が必要ですね。 教えていただいたことをきちんと理解して次につながるようにしたいと思います。 感謝いたします。 ありがとうございました!

その他の回答 (3)

noname#35109
noname#35109
回答No.3

#1です。 > これじゃダメみたいです。。。 > どこを修正すればいいかよろしければ教えていただけないでしょうか。。。 と書かれましても...??? #1では, Flash Lite 1.1 で,四角 と 四角,円と円の当たり判定はできているという条件で回答したのですが, そこはよろしいでしょうか? Flash Lite では,onMouseMove どころか onEnterFrame などが使えないのですから, スクリプト云々ではなく,そういう構造自体を自作しないとならないのですが。 書かれていらっしゃるような定数を用意しても,動く物の座標などは常に変わりますから, そういう静的スクリプトを用意してもどうにもなりませんし, 検証のしようもありませんし, どこを修正すると言われましても, 何をどういう状況で作られたスクリプトなのかわかりません。 あえて言うなら,全てを作り替える??? しかし,どこまでできているのかもわかりませんから, 全て作り替える必要もないかもしれません。 普通の Flash のように,「簡単な例」 をサンプルとして回答することも不可能ですね。 パッと見た限りでは, ah = blue.height // 高さ  ↓変更↓ ah = blue._height;// 高さ でしょうね。 また,if文が変です。 すべての条件が満たされたときですから,else if ではありません。 if(○○){   if(○○){     if(○○){       if(○○){        何か実行       }     }   } } というような形になるはずです。 しかし,そこを変えても構造自体がダメな物はダメです。 一体全体, 四角をどうやって動かして, どのようなタイミングで ah = blue._height; を求めたり, どのようなタイミングでif文判定をしていらっしゃるのでしょうか? と書きましても, Flash Lite の場合,そう安々と補足していただくこともできませんよね。 困った。

lite090
質問者

補足

sassakunさん、ありがとうございました。 まだまだ勉強不足で申し訳ございません。 まず、当たり判定についての考え方はこちらのサイトを参考に作っていました。 http://hakuhin.hp.infoseek.co.jp/main/as/hittest.html#HITTEST_04 四角の移動はmc内にて 1フレーム目に初期位置 2フレーム目に flg=1; spd=3; _x += flg*spd; 3フレーム目に gotoAndPlay(2); と処理し、円に当たるよう横移動するように致しました。 この際の当たり判定を求めたいと思っています。 メインフレーム1フレーム目に 四角のインスタンス(インスタンス名:blue)と円のインスタンス(インスタンス名:red)を配置し、当たり判定のスクリプトもフレームに記述しています。 そもそも、最終的にはランダムに動く対象(四角)が円に当たった時に別のアクションを作りたいと思っています。 しかしながら、お察しの通り1.1での当たり判定は経験がなく、まずは当たり判定(hitTest()を使わない)を理解しなくてはならず四苦八苦しているところです。 状況的にはこのような感じです。 まずは上に書いたようなシンプルな環境で成立させたいと思っています。説明に不足があればご指摘ください。

  • is_may
  • ベストアンサー率65% (58/89)
回答No.2

Flash Lite1.1の場合、ムービークリップの座標や大きさは getProperty("インスタンス名",プロパティ);//読み取り setProperty("インスタンス名",プロパティ,値);//設定 を使います。この場合は ax = getProperty("blue",_x); // x 座標 ay = getProperty("blue",_y; // y 座標 aw = getProperty("blue",_width); // 幅 ah = getProperty("blue",_height); // 高さ //円(red) bx = getProperty("red",_x); // 中心 x 座標 by = getProperty("red",_y); // 中心 y 座標 br = getProperty("red",_width)/2; // 半径 こんなカンジになります。

lite090
質問者

補足

is_mayさん、ありがとうございました。 勉強になります。

noname#35109
noname#35109
回答No.1

円を●,矩形を□として書きます。 また,● も □ も基準点がそれらの中央にあったとします。 □ に ● が当たるとは次のような感じになるということです。  ●●●  ●□●  ●●● 上の場合,□ を基準に考えていますが, 当たり判定は,どっちを基準に考えても同じです。 結局, ●の半径の分, □が外に広がったエリア内に, ●の基準点が入ったとき, □と●は当たったと言うことになると思います。 □が●の半径分拡大された点に●の中心が来たときと考えれば良いということです。 □ が □ の状態だと次のようになります。 ●._x <= □._x + (□.横幅/2) + ●の半径 ●._x >= □._x - (□.横幅/2) - ●の半径 ●._y <= □._y + (□.高さ/2) + ●の半径 ●._y >= □._y - (□.高さ/2) - ●の半径 この全ての条件が重なったとき, ●と□は当たったと言えると思います。 もし,□ が ◇ の状態だと・・・, その場合はよくわかりませんね。

lite090
質問者

お礼

sassakunさん、ありがとうございました。 アドバイス頂いたことを参考に書いてみました。 1フレーム目にAS記述、インスタンスを配置し //四角(blue:横移動し円に当たるようにしました) ax = blue._x; // x 座標 ay = blue._y; // y 座標 aw = blue._width; // 幅 ah = blue.height // 高さ //円(red) bx = red._x; // 中心 x 座標 by = red._y; // 中心 y 座標 br = red._width / 2; // 半径 if( bx <= ax+aw/2+br){ }else if(bx >= ax-aw/2-br){ }else if( by <= ay+ah/2+br){ }else if( by >= ay-ah/2-br){ }else{ trace("hit"); // 当たりあり } これじゃダメみたいです。。。 どこを修正すればいいかよろしければ教えていただけないでしょうか。。。

関連するQ&A