HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0603
金欠師匠スクロール活用の当たり判定7未解決


金欠師匠

リンク

2018/6/3(Sun) 17:49:43|NO.84545

どっかのゲーム似なんですが、今回は当たり判定を改善してほしいです。
いろいろ試してたんでしたが、敵と弾丸が衝突してもダメージを受けない...
というより別の座標の敵がダメージを受けます...T_T
どなたでもいいので当たり判定の if処理 をどうすればいいのか教えてください!!
お願いします。


#module #deffunc exmes str prm1 txt = prm1 cx = ginfo(22) cy = ginfo(23) color 0, 0, 0 pos ( cx - 1 ), ( cy - 1 ) mes txt pos cx, ( cy - 1 ) mes txt pos ( cx + 1 ), ( cy - 1 ) mes txt pos ( cx - 1 ), cy mes txt pos ( cx + 1 ), cy mes txt pos ( cx - 1 ), ( cy + 1 ) mes txt pos cx, ( cy + 1 ) mes txt pos ( cx + 1 ), ( cy + 1 ) mes txt color 255, 255, 255 pos cx, cy mes txt return #deffunc RegularPolygon int prm1, int prm2, int prm3, int prm4, int prm5 center_x = prm1 center_y = prm2 num_top = prm3 radius = prm4 startθ = prm5 if num_top < 3 { return 1 } if radius < 1 { return 1 } dim arrange_x, 4 dim arrange_y, 4 rad0 = double(360) / num_top repeat num_top rad1 = deg2rad(rad0 * (cnt + 1)) + startθ + 1.5707963 rad2 = deg2rad(rad0 * cnt) + startθ + 1.5707963 arrange_x = center_x + (cos(rad1) * radius), center_x + (cos(rad2) * radius), center_x, center_x arrange_y = center_y - (sin(rad1) * radius), center_y - (sin(rad2) * radius), center_y, center_y gsquare -1, arrange_x, arrange_y loop return 0 #global // *** ウィンドウの作成や設定 *** \\ bgscr 0, ginfo(20), ginfo(21), 0, 0, 0 title "Shape War" // *** 自機の弾丸描画 *** \\ buffer 1 color 255, 0, 0 circle 0, 0, 15, 15, 1 color 0, 0, 0 circle 0, 0, 15, 15, 0 gsel 0 // *** 敵の描画1 *** \\ buffer 100 color 0, 0, 0 boxf 0, 0, 30, 30 color 255, 255, 100 boxf 1, 1, 28, 28 gsel 0 // *** 敵の描画2 *** \\ buffer 101 color 255, 128, 128 circle 0, 0, 30, 30, 1 color 0, 0, 0 circle 0, 0, 30, 30, 0 gsel 0 // *** 敵の描画3 *** \\ buffer 102 color 0, 0, 0 RegularPolygon 31, 31, 5, 32, 0 color 128, 128, 255 RegularPolygon 31, 31, 5, 30, 0 gsel 0 // *** 敵の描画4 *** \\ buffer 103 color 0, 0, 0 RegularPolygon 121, 121, 5, 122, 0 color 128, 128, 255 RegularPolygon 121, 121, 5, 120, 0 gsel 0 // *** 変数宣言 *** \\ stx = 1.0 * ginfo(20) * 0.5 sty = 1.0 * ginfo(21) * 0.5 MyAtkBallSpeed = 3.00 MaxMyAtkBallNumber = 1024 ddim MyAtkBall, MaxMyAtkBallNumber, 6 MaxAllEnemyNumber = 1024 ddim Enemy, MaxAllEnemyNumber, 6 MyMaxSpeed = 5.00 // *** メイン処理 *** \\ randomize repeat redraw 0 color 255, 255, 255 boxf stick key, 256 gosub *draw_myball gosub *draw_enemy gosub *draw_my redraw 1 await 16 time = time + 1 loop // *** 自機の弾丸を描画 *** \\ *draw_myball auto = 1 if (( key = 256 ) | auto = 1 ) & ( time \ 5 = 0 ) { MyAtkBallNumber = MyAtkBallNumber + 1 if MyAtkBallNumber >= MaxMyAtkBallNumber { MyAtkBallNumber = 0 } MyAtkBall(MyAtkBallNumber, 0) = stx + mx MyAtkBall(MyAtkBallNumber, 1) = sty + my MyAtkBall(MyAtkBallNumber, 2) = atan(mousey-sty,mousex-stx)*180/M_PI MyAtkBall(MyAtkBallNumber, 3) = MyAtkBallSpeed MyAtkBall(MyAtkBallNumber, 4) = 1.0 MyAtkBall(MyAtkBallNumber, 5) = 0.0 } MyAtkBallGetNumber = 0 repeat ( MaxMyAtkBallNumber - 1 ) if MyAtkBall(cnt, 4) = 1.0 { MyAtkBall(cnt, 5) = MyAtkBall(cnt, 5) + 1 MyAtkBall(cnt, 0) = MyAtkBall(cnt, 0) + ( MyAtkBall(cnt, 3) * cos( 3.141593 * MyAtkBall(cnt, 2) / 180 )) MyAtkBall(cnt, 1) = MyAtkBall(cnt, 1) + ( MyAtkBall(cnt, 3) * sin( 3.141593 * MyAtkBall(cnt, 2) / 180 )) color 255, 255, 255 gmode 4, 0, 0, 256 pos MyAtkBall(cnt, 0) - mx, MyAtkBall(cnt, 1) - my gcopy 1, 0, 0, 15, 15 pos MyAtkBall(cnt, 0) - mx, MyAtkBall(cnt, 1) - my - 45 if MyAtkBall(cnt, 5) >= 120.0 { MyAtkBall(cnt, 5) = 0.0 MyAtkBall(cnt, 4) = 0.0 } MyAtkBallGetNumber = MyAtkBallGetNumber + 1 } loop return // *** 敵の描画 *** \\ *draw_enemy font "メイリオ", 30, 1 repeat ( MaxAllEnemyNumber - 1 ) if Enemy(cnt, 3) = 0 { Enemy(cnt, 0) = 1.0 * rnd(10000) Enemy(cnt, 1) = 1.0 * rnd(10000) if rnd(10) = 0 { Enemy(cnt, 2) = 0.0 } if rnd(25) = 0 { Enemy(cnt, 2) = 1.0 } if rnd(50) = 0 { Enemy(cnt, 2) = 2.0 } if rnd(100) = 0 { Enemy(cnt, 2) = 3.0 } Enemy(cnt, 3) = 1.0 if Enemy(cnt, 2) = 0 { EnemyMaxHP = 10 } if Enemy(cnt, 2) = 1 { EnemyMaxHP = 30 } if Enemy(cnt, 2) = 2 { EnemyMaxHP = 100 } if Enemy(cnt, 2) = 3 { EnemyMaxHP = 3000 } Enemy(cnt, 4) = 1.0 * EnemyMaxHP Enemy(cnt, 5) = Enemy(cnt, 4) } if Enemy(cnt, 0) - mx >= -500 & Enemy(cnt, 1) - my >= -500 & Enemy(cnt, 0) - mx <= ( ginfo(20) + 500 ) & Enemy(cnt, 1) - my <= ( ginfo(21) + 500 ) { if Enemy(cnt, 3) = 1 { if Enemy(cnt, 2) = 0 { color 255, 255, 255 gmode 4, 0, 0, 256 pos Enemy(cnt, 0) - mx, Enemy(cnt, 1) - my gcopy 100, 0, 0, 30, 30 } if Enemy(cnt, 2) = 1 { color 255, 255, 255 gmode 4, 0, 0, 256 pos Enemy(cnt, 0) - mx, Enemy(cnt, 1) - my gcopy 101, 0, 0, 30, 30 } if Enemy(cnt, 2) = 2 { color 255, 255, 255 gmode 4, 0, 0, 256 pos Enemy(cnt, 0) - mx, Enemy(cnt, 1) - my gcopy 102, 0, 0, 60, 60 } if Enemy(cnt, 2) = 3 { color 255, 255, 255 gmode 4, 0, 0, 256 pos Enemy(cnt, 0) - mx, Enemy(cnt, 1) - my gcopy 103, 0, 0, 240, 240 pos Enemy(cnt, 0) - mx - 11, Enemy(cnt, 1) - my - 45 exmes "Alpha Pentagon" } pos Enemy(cnt, 0) - mx - 11, Enemy(cnt, 1) - my - 100 if Enemy(cnt, 5) < Enemy(cnt, 4) { if Enemy(cnt, 2) = 0 | Enemy(cnt, 2) = 1 { if Enemy(cnt, 5) > 0 { color 100, 100, 100 boxf ( Enemy(cnt, 0) - mx - 10 ), ( Enemy(cnt, 1) - my + 32 ), ( Enemy(cnt, 0) - mx + 40 ), ( Enemy(cnt, 1) - my + 38 ) color 128, 0, 0 boxf ( Enemy(cnt, 0) - mx - 8 ), ( Enemy(cnt, 1) - my + 34 ), ( Enemy(cnt, 0) - mx + 38 ), ( Enemy(cnt, 1) - my + 36 ) color 0, 192, 0 boxf ( Enemy(cnt, 0) - mx - 8 ), ( Enemy(cnt, 1) - my + 34 ), (( Enemy(cnt, 0) - mx - 8 ) + ( Enemy(cnt, 5) / Enemy(cnt, 4) ) * 46 ), ( Enemy(cnt, 1) - my + 36 ) } } if Enemy(cnt, 2) = 2 { if Enemy(cnt, 5) > 0 { color 100, 100, 100 boxf ( Enemy(cnt, 0) - mx ), ( Enemy(cnt, 1) - my + 62 ), ( Enemy(cnt, 0) - mx + 60 ), ( Enemy(cnt, 1) - my + 68 ) color 128, 0, 0 boxf ( Enemy(cnt, 0) - mx + 2 ), ( Enemy(cnt, 1) - my + 64 ), ( Enemy(cnt, 0) - mx + 58 ), ( Enemy(cnt, 1) - my + 66 ) color 0, 192, 0 boxf ( Enemy(cnt, 0) - mx + 2 ), ( Enemy(cnt, 1) - my + 64 ), (( Enemy(cnt, 0) - mx ) + ( Enemy(cnt, 5) / Enemy(cnt, 4) ) * 46 ), ( Enemy(cnt, 1) - my + 66 ) } } if Enemy(cnt, 2) = 3 { if Enemy(cnt, 5) > 0 { color 100, 100, 100 boxf ( Enemy(cnt, 0) - mx ), ( Enemy(cnt, 1) - my + 223 ), ( Enemy(cnt, 0) - mx + 240 ), ( Enemy(cnt, 1) - my + 231 ) color 128, 0, 0 boxf ( Enemy(cnt, 0) - mx + 2 ), ( Enemy(cnt, 1) - my + 225 ), ( Enemy(cnt, 0) - mx + 238 ), ( Enemy(cnt, 1) - my + 229 ) color 0, 192, 0 boxf ( Enemy(cnt, 0) - mx + 2 ), ( Enemy(cnt, 1) - my + 225 ), (( Enemy(cnt, 0) - mx ) + ( Enemy(cnt, 5) / Enemy(cnt, 4) ) * 239 ), ( Enemy(cnt, 1) - my + 229 ) } } } } } ////////////////////////////////////////// 当たり判定 /////////////////////////////////////// { Enemy(cnt, 5) = Enemy(cnt, 5) - 1.0 } if Enemy(cnt, 5) <= 0.0 { Enemy(cnt, 3) = 0.0 if Enemy(cnt, 2) = 0 { score = score + 10 } if Enemy(cnt, 2) = 1 { score = score + 25 } if Enemy(cnt, 2) = 2 { score = score + 130 } if Enemy(cnt, 2) = 3 { score = score + 3000 } } loop return // *** 自機を描画 *** \\ *draw_my color 255, 0, 0 circle stx - 30, sty - 30, stx + 30, sty + 30, 1 color 0, 0, 0 circle stx - 30, sty - 30, stx + 30, sty + 30, 0 getkey keyW, 'W' getkey keyA, 'A' getkey keyS, 'S' getkey keyD, 'D' brake = ( 0.05 ) if keyW = 1 { mmyy = mmyy + 0.1 my = my - ( mmyy + 1.0 ) if mmyy >= MyMaxSpeed { mmyy = MyMaxSpeed } } else { mmyy = mmyy - brake my = my - mmyy if mmyy <= 0.0 { mmyy = 0.0 } } if keyA = 1 { mmyx = mmyx + 0.1 mx = mx - ( mmyx + 1.0 ) if mmyx >= MyMaxSpeed { mmyx = MyMaxSpeed } } else { mmyx = mmyx - brake mx = mx - mmyx if mmyx <= 0.0 { mmyx = 0.0 } } if keyS = 1 { pmyy = pmyy + 0.1 my = my + ( pmyy + 1.0 ) if pmyy >= MyMaxSpeed { pmyy = MyMaxSpeed } } else { pmyy = pmyy - brake my = my + pmyy if pmyy <= 0.0 { pmyy = 0.0 } } if keyD = 1 { pmyx = pmyx + 0.1 mx = mx + ( pmyx + 1.0 ) if pmyx >= MyMaxSpeed { pmyx = MyMaxSpeed } } else { pmyx = pmyx - brake mx = mx + pmyx if pmyx <= 0.0 { pmyx = 0.0 } } color 0, 0, 0 pos 10, 10 font "メイリオ", 30, 1 exmes "Score:" + score return



この記事に返信する


あらや

リンク

2018/6/4(Mon) 02:08:21|NO.84548

弾と敵の配列変数の意味がいまいちわかりにくいですね。
まあ、ソースからおおよそそ推察できましたが
コメント無しでいきなり理解しろというのは、ちょっと無茶ではないかと……。

/* MyAtkBall(cnt, 0) // 弾 左上座標X MyAtkBall(cnt, 1) // 弾 左上座標Y MyAtkBall(cnt, 2) // 弾 移動方向(角度) MyAtkBall(cnt, 3) // 弾 移動速度 MyAtkBall(cnt, 4) // 弾 描画フラグ(1なら描画) MyAtkBall(cnt, 5) // 弾 描画フレーム数(120以上になったら消滅) Enemy(cnt, 0) // 敵 左上座標X Enemy(cnt, 1) // 敵 左上座標Y Enemy(cnt, 2) // 敵 種別 Enemy(cnt, 3) // 敵 描画フラグ(1なら描画) Enemy(cnt, 4) // 敵 最大HP Enemy(cnt, 5) // 敵 現在HP */
たぶんこんな感じの意味ですよね?
このように配列の各要素に対してコメントを書いておかないと
時間が経ったら自分でも意味がわからなくなると思います。



そして本題ですが、
五角形(敵)と円(弾)の衝突判定は可能ですが少々難易度が高いので
とりあえずは円と円の衝突判定(円の中心座標と半径がわかれば距離を測るだけ)のような
単純な物から始めてはいかがでしょうか?

その後で円と矩形(boxfで描けるような四角形)の衝突判定などをやってみてから
五角形に挑戦してみるのがいいかと思います。



金欠師匠

リンク

2018/6/4(Mon) 07:03:49|NO.84549

おっと。
コメントを付けるのを忘れてしまいました(^^;
あらやさんので合っています。
本当にすいません...m(-_-)m



金欠師匠

リンク

2018/6/4(Mon) 07:14:51|NO.84550

もう少し、詳しく言います。
>いろいろ試してたんでしたが、敵と弾丸が衝突してもダメージを受けない...
↑は最初は四角形を試していました

最も簡単な四角形から分からなかくなる未熟者ですが...
よろしくお願いしますm(-_-)m



暇人

リンク

2018/6/4(Mon) 20:09:59|NO.84551

スクリーン座標と実座標がごっちゃになってるんじゃ?

MyAtkBall(cnt, 0) // 弾 左上座標X MyAtkBall(cnt, 1) // 弾 左上座標Y Enemy(cnt, 0) // 敵 左上座標X Enemy(cnt, 1) // 敵 左上座標Y
これには実座標が入ってるみたいだから
これを判定処理すればスクロールしてようが関係ない


> if Enemy(cnt, 0) - mx >= -500 & Enemy(cnt, 1) - my >= -500 & Enemy(cnt, 0) - mx <= ( ginfo(20) + 500 ) & Enemy(cnt, 1) - my <= ( ginfo(21) + 500 ) {
> if Enemy(cnt, 3) = 1 {
↑これの下辺りに

esx=30.0 esy=30.0 ex=Enemy(cnt, 0)+esx/2.0-15.0/2 //自弾サイズの半分を減算、敵のサイズの半分を加算して中心座標にする ey=Enemy(cnt, 1)+esy/2.0-15.0/2 hsx=(esx+15.0)/2.0 hsy=(esy+15.0)/2.0 Damage=0 repeat MaxMyAtkBallNumber if MyAtkBall(cnt, 4) = 1.0 { difx=ex-MyAtkBall(cnt, 0) dify=ey-MyAtkBall(cnt, 1) if absf(difx)<hsx and absf(dify)<hsy { Damage++ } } loop if Damage>0 { Enemy(cnt, 5)-Damage }
をコピペすればサイズ30の四角形判定は出来る

MaxMyAtkBallNumberが1024と多くて無駄に処理食うので24ぐらいで良いと思う

> repeat ( MaxMyAtkBallNumber - 1 )
だと最後の一つが移動処理されずに残る



あらや

リンク

2018/6/4(Mon) 20:51:37|NO.84552

>最も簡単な四角形から分からなかくなる未熟者ですが...
四角形ができないのになぜ五角形を描画しているのかわかりませんが
とりあえず四角形として見た場合の衝突判定だけやってみました。

色々雑なのでどこか間違えているかもしれませんが
やっていることは、四角形の中に弾が入っているかを
全ての弾の位置と敵の位置から判定するだけです。

なお本当に全ての弾(1024)だと処理時間がかかりすぎるので、50個だけにしています。
それでも遅いんですが……

////////////////////////////////////////// 当たり判定 /////////////////////////////////////// Ecnt = cnt; ddim MyAtkBallprm, 7; // 弾 各種情報 ddim Enemyprm, 4; // 敵 各種情報 repeat 50 // 1024回ループだと時間が掛かるため適当な回数にしておく if Enemy(Ecnt, 3) = 0 { // 敵 描画オフのときは衝突判定が不要 break; } else { if MyAtkBall(cnt, 4) = 0.0 { // 弾 描画オフのときは衝突判定が不要 continue; } else { // 弾の各種情報 MyAtkBallprm(0) = MyAtkBall(cnt, 0) - mx; // 弾 左上座標X MyAtkBallprm(1) = MyAtkBall(cnt, 1) - my; // 弾 左上座標Y MyAtkBallprm(2) = MyAtkBallprm(0) + 15; // 弾 右下座標X MyAtkBallprm(3) = MyAtkBallprm(1) + 15; // 弾 右下座標Y MyAtkBallprm(4) = (MyAtkBallprm(0) + MyAtkBallprm(2)) / 2.0; // 弾 中心座標X MyAtkBallprm(5) = (MyAtkBallprm(1) + MyAtkBallprm(3)) / 2.0; // 弾 中心座標Y MyAtkBallprm(6) = 15.0 / 2.0; // 弾 半径 // 敵の各種情報 Enemyprm(0) = Enemy(Ecnt, 0) - mx; // 敵 左上座標X Enemyprm(1) = Enemy(Ecnt, 1) - my; // 敵 左上座標Y if Enemy(Ecnt, 2) = 0 { Enemyprm(2) = Enemyprm(0) + 30; // 敵 右下座標X Enemyprm(3) = Enemyprm(1) + 30; // 敵 右下座標Y } if Enemy(Ecnt, 2) = 1 { Enemyprm(2) = Enemyprm(0) + 30; // 敵 右下座標X Enemyprm(3) = Enemyprm(1) + 30; // 敵 右下座標Y } if Enemy(Ecnt, 2) = 2 { Enemyprm(2) = Enemyprm(0) + 60; // 敵 右下座標X Enemyprm(3) = Enemyprm(1) + 60; // 敵 右下座標Y } if Enemy(Ecnt, 2) = 3 { Enemyprm(2) = Enemyprm(0) + 240; // 敵 右下座標X Enemyprm(3) = Enemyprm(1) + 240; // 敵 右下座標Y } // 弾を中心座標を基準にした点として考え // 敵は弾の半径分大きい四角形として考える Enemyprm(0) -= MyAtkBallprm(6); Enemyprm(1) -= MyAtkBallprm(6); Enemyprm(2) += MyAtkBallprm(6); Enemyprm(3) += MyAtkBallprm(6); // 点と四角形の衝突判定 if( (Enemyprm(0) <= MyAtkBallprm(4)) && (MyAtkBallprm(4) <= Enemyprm(2)) && (Enemyprm(1) <= MyAtkBallprm(5)) && (MyAtkBallprm(5) <= Enemyprm(3)) ) { Enemy(Ecnt, 5) -= 1.0; } } } loop
MyAtkBallGetNumberの変数に弾の数を記録しているっぽいですが、
消滅した弾もカウントされていて正確性に欠けるので今回は使いませんでした。



それから、いくつか気になったのですが

毎ループで弾の位置計算にsin、cosを使っていますが
例えば最初の時点で

MyAtkBall(cnt, 6) = MyAtkBall(cnt, 3) * cos( 3.141593 * MyAtkBall(cnt, 2) / 180 ) // 弾 移動量X MyAtkBall(cnt, 7) = MyAtkBall(cnt, 3) * sin( 3.141593 * MyAtkBall(cnt, 2) / 180 ) // 弾 移動量Y
とすれば位置を更新するときに

MyAtkBall(cnt, 0) += MyAtkBall(cnt, 6) MyAtkBall(cnt, 1) += MyAtkBall(cnt, 7)
こう書くだけで済み、計算量が減るので高速化できるのではないかと。



ほかにも

if Enemy(cnt, 2) = 0 { // 敵の種別が0のときの処理 } if Enemy(cnt, 2) = 1 { // 敵の種別が1のときの処理 } if Enemy(cnt, 2) = 2 { // 敵の種別が2のときの処理 } if Enemy(cnt, 2) = 3 { // 敵の種別が3のときの処理 }
こういう条件分けの処理を何度もやっていますが
配列変数の要素を増やして、大きさや倒した時のスコアなどなどを最初の時点で記録しておけば
条件分けしなくても全て同じ処理で書くこともできるのでは無いかなと思います。

とりあえずはスクロール要素を入れたせいでかなり複雑化している気がするので
一旦スクロール無しでやってみるのがいいかもしれません。

そして敵と弾の最大数がどちらも1024というのは、
処理時間的な問題で多すぎるかもしれません。
敵1体に対して全ての弾の衝突判定をするということは
毎フレーム1048576(1024*1024)回も衝突判定を行なうということになるので
かなり低速化します。



金欠師匠

リンク

2018/6/5(Tue) 06:39:56|NO.84553

まだまだ、自分が初心者だとすぐ分かりますw(^^;

>四角形ができないのになぜ五角形を描画しているのかわかりませんが
アレですね、最初は全部四角形にしようと思ったんですけど、
後々、正確な判定に変えたのです。

ありがとうございます。



金欠師匠

リンク

2018/6/5(Tue) 06:45:07|NO.84554

お二方本当にありがとうございました。



ONION software Copyright 1997-2023(c) All rights reserved.