DxObjectの当たり判定
投稿者 : mmm(softbank220004003130.bbtec.net)
- 2012/02/25(Sat) 20:11
No.13527
|
|
|
|
|
13527.zip
こんにちは、文字色を変えてみましたmmmです。
しばらくするとレーザー発射を始めるのですが、 ボスが空中浮遊しながらレーザーを撃つようになってからが問題です。 レーザーを回転させていると、当たり判定が変なところで取られてしまいます。当たっているのにとられないこともあります。 例としては、地面と離れているブロックの中で一番下のブロック(右)に乗っていると、 レーザーが当たってダメージを受け、 レーザーが通り過ぎて、ちょうど線対称の位置にあるブロックにかかるとまたダメージを受けます。
回転させると当たり判定領域が増えるのかと思って、 少し細いあたり判定(添付ゲーム中の黄色いレーザー)を加えてみたのですが、変わりませんでした。 プログラムはご自由に見ていただいてかまいません(汚いプログラムなので恥ずかしいですが)。 操作方法は 上キー ジャンプ 左右キー 横移動 スペースキー 攻撃 です。どうかよろしくお願いします。
|
Re: DxObjectの当たり判定
投稿者 : kazz(ntchba036080.chba.nt.ngn2.ppp.infoweb.ne.jp)
- 2012/02/25(Sat) 22:22
No.13528
|
|
|
|
CrashToの命令の中をのぞいてみればわかるとおもいますが、crashtoはangleをほとんど考慮されていません。
function crashTo(pp,xx,yy){ // 他のオブジェクトと衝突しているかどうかを判定します。<HID=23> if (!pp)return 0; if ( abs(pp.x-(x+xx))*2 < getWidth()+pp.getWidth() ) { return abs(pp.y-(y+yy))*2 < getHeight()+pp.getHeight() ; } return 0; }
ほとんど、というのはgetWidth()とgetHeight()の中にangleを微妙に考慮されているからです。
function getWidth() { var r;r=native_getPWidth(p)*scalex; if (r>24) return r-8; return r*0.66; } function getHeight() { var r,sc; sc=scaley; if (!sc) sc=scalex; r=native_getPHeight(p)*sc; if (r>24) return r-8; return r*0.66; }
native_getPなんとか(p)の中は見れませんが、多分この中でangleをいてれいます。 でも、この当たり判定では変になってしまいます。 例:/ の当たり判定は □ になる。 / の当たり判定は □の半分 になる。
で、解決策ですがcrashtolineを使うのがいいと思います。 crashtolineは線分とオブジェクトの当たり判定を出してくれます。幅も指定できるので、回転攻撃のところに使うといいでしょう。
|
Re: DxObjectの当たり判定
投稿者 : リセッタ(ai126212028176.5.tik.access-internet.ne.jp)
- 2012/02/26(Sun) 01:37
No.13529
|
|
|
|
横から失礼します。
>native_getPなんとか(p)の中は見れませんが、多分この中でangleをいてれいます。
"sprite.tonyu"を見ると、 function getPatWidth(p) { return native_getPWidth(p); } function getPatHeight(p) { return native_getPHeight(p); } と定義されています。パターン番号で示された幅,高さのドット数を返すだけです。angleは考慮されてませんよ。
修正内容 "b3tama2_2.tonyu" extends DxChar;
w=getPatWidth(p)/2; h=getPatHeight(p); // #追加 パターンサイズ取得 ※縮尺は考慮してません。 // "crashTo()"と同等なサイズ(やや小さめ)で判定なら、"getWidth()","getHeight()"にする。
while(1){ c=cos(angle); s=sin(angle); // #追加 cc=w*c; ss=w*s; // #追加 x0=x-cc; x1=x+cc; // #追加 y0=y-ss; y1=y+ss; // #追加 //if(crashTo($syu)){ // #修正 if($syu.crashToLine(x0,y0,x1,y1,h)){ // #修正 ラインで判定
// 略
else die=0; //x=$boss.x+149*cos(angle); // #修正 //y=$boss.y-20+149*sin(angle); // #修正 x=$boss.x+149*c; // #修正 y=$boss.y-20+149*s; // #修正 angle++; update(); }
|
Re: DxObjectの当たり判定
投稿者 : mmm(softbank220004003130.bbtec.net)
- 2012/02/26(Sun) 13:20
No.13530
|
|
|
|
>>パターン番号で示された幅,高さのドット数を返すだけです。angleは考慮されてません >>crashtolineを使うのがいいと思います
kazzさん、リセッタさん、ありがとうございます! 確かに、angleが考慮されていないのであれば元の画像のまま当たり判定を取っているわけですから、 同じ高さにくると当たるわけです。
当たり判定の取り方の例まで示してくださりありがとうございました。さっそくCrashTolineでとってみます。
|
Re: DxObjectの当たり判定
投稿者 : kazz(ntchba036080.chba.nt.ngn2.ppp.infoweb.ne.jp)
- 2012/02/26(Sun) 19:48
No.13531
|
|
|
|
いや、native_getPなんとかって書いたのはnative_getPWidth(p)とnative_getPHEight(p)のことで2こ描くのが面倒だったのでそうしただけです。 plainchar.tonyu(みたいなスペル)に入ってます。
|
Re: DxObjectの当たり判定
投稿者 : リセッタ(ai126241002179.tik.access-internet.ne.jp)
- 2012/02/26(Sun) 22:56
No.13532
|
|
|
|
"native_getPWidth(p)"は"getPatWidth(p)"に, "native_getPHeight(p)"は"getPatHeight(p)"に、 単純に再定義されていますので、"DxChar"クラスで"angle"によって 戻り値が変化する事は無いってことを言いたいんですけど。 (ヘルプ:"Sprite"クラス"getPatWidth(p)","getPatHeight(p)"メソッド参照。 "angle"で変化しちゃうなら、取得する時逆に手間が掛かるよ) 元の記述だと、"native_getPなんとか(p)"が"angle"により戻り値が変わる様に受け取れるのですが。
元の記述 > native_getPなんとか(p)の中は見れませんが、多分この中でangleをいてれいます。
もし、"angle"を考慮しているのかな?と思える箇所は、 "getWidth()","getHeight()"の戻り値がパターン寸法より小さめに返る位だと。
# ただ、この場合も"angle"により変化はしないので経験的な値の様な気がします。 # "SpriteChar"と"DxChar"では、判定範囲が微妙に異なるのも悩み所ですね。
|
Re: DxObjectの当たり判定
投稿者 : mmm(softbank220004003130.bbtec.net)
- 2012/02/28(Tue) 19:44
No.13533
|
|
|
|
13533.txt
どうしてもcrashToLineのとり方がうまくいきません。 添付プログラムの /* */ をはずすと、「不正な浮動小数点除算」のエラーが出てしまいます。 crashToLine(sx,sy,dx,dy)の(sx,sy),(dx,dy)の座標が同じだとエラーが出る、ということが書いてあったので調べてみましたが、 個人的にはその点は問題ないと感じました。
添付プログラム、$B3では無く$bossということでお願いします。すみません。
ご教授いただいたプログラムではうまくいかなかった為、 少し違う方法でとろうとしています。 結局どちらも自分の手に負えなかったので、sin,cosのやり方、これでいいのでは?というのがあればお教えください。 お願いします。
|
Re: DxObjectの当たり判定
投稿者 : リセッタ(ai126213020078.5.tss.access-internet.ne.jp)
- 2012/02/29(Wed) 00:00
No.13534
|
|
|
|
>ご教授いただいたプログラムではうまくいかなかった為、 動作確認して問題なさそうだからコピペしたんだけど? どんな問題があったのかな?コピペミス?
# もしかして、 # w=getPatWidth(p)/2; // <-"/2"忘れてない?中心からの距離を設定ですよ。
さて、"13533.txt"が新"b3tama2_2.tonyu"で"boss.tonyu"がそのままだと仮定すると、エラーが出るでしょう。 "boss.tonyu"から"b3tama2_2"クラスの呼び出し部分を見ると appear(new b3tama2_2(x,y-20,$pat_boss3+38)); // "x"->"x+149" id2=appear(new b3tama2_2(x,y-20,$pat_boss3+38)); // "x"->"x-149"
"13533.txt"が、 extends DxChar; id=appear(new b3tama3($boss.x,$boss.y-20,3)); while(1){ // 略 if(x==id.x){ xs=x; xe=x; } // 略 if(y==id.y){ ys=y; ye=y; } // 略
で"b3tama2_2"の"x,y"と"id.x,id.y"の初期値が同じになります。 すると、最初の"xs,ys","xe,ye"が同じになります。
# 参)constructor DXChar(x,y,p[,f,scaleX,angle,alpha])
>個人的にはその点は問題ないと感じました。 感じただけでなく、"print()"メソッド等で確認することです!
# "13533.txt"で"b3tama3"クラスを作ってるけど、 # xo=$boss.x; yo=$boss.y-20; # とでも定義して、"id,x,id.y"を"xo,yo"に置き換えれば良いんじゃない。
|
Re: DxObjectの当たり判定
投稿者 : mmm(softbank220004003130.bbtec.net)
- 2012/02/29(Wed) 22:50
No.13535
|
|
|
|
>>どんな問題があったのかな?コピペミス? 残念なことにというか嬉しい事にというか、コピペミスでした。 w=getPatWidth(p)/2; の (p) を () にしてしまったのです。 お騒がせして申し訳ありませんでした。 参照するものが必要なことくらいわかりそうなものですが、 コピペをするとどうしてもヘルプを確認しながら一つずつ入力、という工程が抜けてしまうのです。 そこが自分のコピペの弱いところ(まるごとコピペしていれば防げたのですが)ですね。
>>感じただけでなく、"print()"メソッド等で確認することです! 言葉が足りませんでした。個人的には問題ないと"思った"ということです。 print()での確認、プログラム見直しはいつもやっています(今後は写し間違いにも気をつけなければいけませんが)。
あと、縦一直線になったとき xs=xe で、 横一直線になったとき ys=ye ではないですか? 初期値がすべて同じになってしまうというのがまだわかりません。そこのところを詳しくお願いします。
|
Re: DxObjectの当たり判定
投稿者 : リセッタ(ai126212006248.5.tik.access-internet.ne.jp)
- 2012/03/01(Thu) 00:51
No.13537
|
|
|
|
>初期値がすべて同じになってしまうというのがまだわかりません。 ……あの初期値はmmmさんが何にするか決めて渡しているんですよね? 何を渡しているのかを考えれば同じになってるのは分かるとおもうんだけど? "Tonyu System"が、勝手に(暗黙の初期値"null"を)入れてるわけではないんですよ。
"boss.tonyu" appear(new b3tama2_2(x,y-20,$pat_boss3+38)); を実行すると、 <b3tama2_2>.x←[$boss.]x, <b3tama2_2>.y←[$boss.]y-20, <b3tama2_2>.p←$pat_boss3+38 を初期値として"b3tama2_2"クラスを実行するのは理解できますか? そして、 "13533.txt" id=appear(new b3tama3($boss.x,$boss.y-20,3)); が実行されると、 id.x←$boss.x, id.y←$boss.y-20, id.p←3 が初期値として"id"オブジェクトが"b3tama3"クラスで実行されます。
>あと、縦一直線になったとき xs=xe で、横一直線になったとき ys=ye ではないですか? 結果的にはそれも判定できますが、"x=id.x & y=id.y"("<b3tama2_2>"と"id"が同じ位置「重なって」でも)"xs=xe,ys=ye"になるでしょ?
# もう少し、デバッグ能力を磨いてください。 # 設計時は、「こうすればこう動く」筈で作りますが、 # デバッグ時は、自分がPCに成ったつもりで「この命令ならこう動く」、 # 「こう動いてるから、この値はこうなんじゃないか?じゃぁなんでそうなる」を探さないとだめです。 # >print()での確認、プログラム見直しはいつもやっています(今後は写し間違いにも気をつけなければいけませんが)。 # print()で値を見て変なら、その値の作成元を更に確認していかなきゃ、その繰り返しですよ。 # 写し間違いについては、それ程気をつけなくても良いと自分は思いますよ。 # 回答者のプログラムは実際動かしていない場合もあるし、回答者の写し間違いもありえますから(信頼性がいまいち)。 # あくまで参考にするだけで、検証は質問者がしなければなりません。 # まぁ、回答者に動かないよ〜、ヘルプ〜でも良いですけど。
# 今回の例では、 # 1.エラー → どんな時エラーになる? # 2."xs=xe&ys=ye"でエラー → "x=id.x"で"xs=xe=x"、"y=id.y"で"ys=ye=y"同時になった時エラーみたいだ。 # 3.きちんと動いていれば同時には起こらない筈だ。確認のため"x,id.x,y,id.y"を見てみよう。 # 4."print(x); print(id.x); print(y); print(id.y);"追加。 # 5.1回目で同じ値か?そういや初期値はどうなってるんだ? # 6.バグ発見。初期値を直してOK(^^V # 7.(発展)初期値で動作エラーは気持ち悪いな。重なった場合は"crashToLine()"飛ばしてみるか?"x,y"の再作成の位置を"while()"直後に移動するのはどうだ? # みたいな流れになる筈なんだけど?
|
Re: DxObjectの当たり判定
投稿者 : mmm(softbank220004003130.bbtec.net)
- 2012/03/01(Thu) 21:40
No.13538
|
|
|
|
なるほど。要するに w=getPatWidth(p)/2; を w=getPatWidth()/2; にしてしまったがために、 計算式その他はあっていたのに、w=null ですから初期値変わらず↓ crashToLine()の性質(?)から、xs=xe,ys=yeとなってしまいエラー。 というわけですね。やっと分かりました。どうもありがとうございました。
|
Re: DxObjectの当たり判定
投稿者 : リセッタ(em1-113-209-246.pool.e-mobile.ne.jp)
- 2012/03/01(Thu) 22:36
No.13539
|
|
|
|
>なるほど。要するに w=getPatWidth(p)/2; …… 13529の修正例を手入力したプログラムのデバッグ(ソーストレース)して見たのですね。 しっかりソース追えているみたいで良いですね。
>w=null ですから初期値変わらず……やっと分かりました。 えーと、お互い話が食い違ったのかも。 自分: mmmさんが独自に考えた"13533.txt"の初期値が一緒。 自分で設定したなら判るでしょ? mmmさん: 13529の修正例での初期値が判らない。 そう言うことなら、確かに初期値はテストなりをしないと判らないね。 きつめのコメントはすいませんでしたね。
#--- おまけ ---- DxChar用 回転衝突判定関数
// 角度("angle")対応型衝突判定関数(<DxChar>クラス用) // Syntax) // crashAtAngle(o) オブジェクト"o"の中心と衝突してるか返す // crashAtAngle(m,n) 座標"m,n"と衝突してるか返す // Out) // 戻り値 0:外れ !0:当たり // #ToじゃなくAtなのは、点を判定してるから(個人の趣味です) // #奇数幅のオブジェクトの判定が微妙かも、半ドットずれているかな? function crashAtAngle(pp,yy) { var w,h, sx,sy, ex,ey, dx,dy; if(pp is PlainChar) { // →"pp"は<PlainChar>派生オブジェクト dx=pp.x; dy=pp.y; // 判定オブジェクト→判定座標 } else { dx=pp; dy=yy; // 指定座標→判定座標 } h=getWidth()/2; // 中心〜端の距離(仮) w=cos(angle)*h; // X差分作成 h=sin(angle)*h; // Y差分作成(仮) sx=x-w; ex=x+w; // 判定線分座標作成 sy=y-h; ey=y+h; h=getHeight(); // 高さ=判定線分幅 if(sx==exx && sy==ey) // 判定線分が点? return (sx==dx && sy==dy); // →点同士の判定結果を返す // 線分衝突判定結果を返す return crashToLine(sx,sy,ex,ey,h,dx,dy); }
|
|