当たり判定の動作

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

当たり判定の動作

#1

投稿記事 by sozai » 6年前

現在ゲームとはいえないソフトを作っておりまして、
当たり判定を実装したのですが、なぜか動作しません。
原因は条件式のほうでなく関数の位置にあるのだと思いますがどうなのでしょうか?
関係あると思われる箇所のみ載せます。

コード:

//enemy.cpp
void GameOver_S1(){[tab=30]//当たり判定を行う関数

    if( ((x_Draw-x_e1)*(x_Draw-x_e1)+(y_Draw-y_e1)*(y_Draw-y_e1))<=((75+13)*(75+13)) ) {          //Draw_x,Draw_yは
                                               //プレイヤーが操作するアイコンの座標
	   MessageBox(GetMainWindowHandle(),"Game Over!\nメニューへ戻ります。","GAME OVER",MB_OK);
	   Scene = eScene_Menu;   //メニューへ戻るための処理
    
    }

    if( (x_Draw-x_e2)*(x_Draw-x_e2)+(y_Draw-y_e2)*(y_Draw-y_e2)<=(75+10)*(75+10) ) {  //x_e1やy_e1,x_e2,y_e2は敵の座標
	    MessageBox(GetMainWindowHandle(),"Game Over!\nメニューへ戻ります。","GAME OVER",MB_OK);
	    Scene = eScene_Menu;
    }

}

コード:

//enemy.h
//ヘッダの宣言
extern void GameOver_S1();

コード:

//Scene.cpp
//現在の場面に関する関数
#include "enemy.h"

void Stage1(){   //ステージ1関連の関数をまとめた関数
    
    GameOver_S1();
    The_Func();   //アイコンの描画や操作関係
    Other_Func(); //ステージクリア時の処理
    Draw_enemy();//敵の描画

    if(Key[ KEY_INPUT_SPACE ]>=1){
	   Scene = eScene_Menu;//スペースキーでメニューへ
    }
}
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#2

投稿記事 by softya(ソフト屋) » 6年前

プログラマが必ず身につけないといけないデバッグ方法ですが、
ここの式が
if( ((x_Draw-x_e1)*(x_Draw-x_e1)+(y_Draw-y_e1)*(y_Draw-y_e1))<=((75+13)*(75+13)) ) {
どうなって真偽判定されているかデバッガでも確認できません。
これではデバッグできないので、
式をif文と分離してください。
int diff_x = (x_Draw-x_e1);
int diff_y = (y_Draw-y_e1);
こうすれば、それぞれの値を確認できます。

>原因は条件式のほうでなく関数の位置にあるのだと思いますがどうなのでしょうか?
このコードだけだと処理順番がわかりませんので、答えることは無理ですね。
少なくともデバッガでGameOver_S1が適切なタイミングで呼ばれていることは確認できると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#3

投稿記事 by sozai » 6年前

softya(ソフト屋) さんが書きました: >原因は条件式のほうでなく関数の位置にあるのだと思いますがどうなのでしょうか?
このコードだけだと処理順番がわかりませんので、答えることは無理ですね。
少なくともデバッガでGameOver_S1が適切なタイミングで呼ばれていることは確認できると思います。
では、他に必要なコードはどのような箇所でしょうか?
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#4

投稿記事 by softya(ソフト屋) » 6年前

デバッガで毎フレーム適切に呼び出されいる事は確認されましたか?
Stage()が毎フレーム呼び出されるなら、GameOver_S1()も毎フレーム呼び出されているはずです。

> では、他に必要なコードはどのような箇所でしょうか?
出来るだけご自分で確認してもらいたいのですが、無理そうですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#5

投稿記事 by sozai » 6年前

環境はVisualC++Express2010を使っています。
デッバグして実行したところ、ちゃんと敵もユーザーが操作するアイコンのほうも描かれましたし動かすことも出来ましたので、毎フレームにStage1()が呼び出されているのだとは思います。
敵のアイコンにぶつかると、時々動きが微かに鈍くなるような気がしたので、変数を使い、Game Overか否かを判断するように変えてみようと思います。
>出来るだけご自分で確認してもらいたいのですが、無理そうですか?
わかりました。
もう一度見直してみます。
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#6

投稿記事 by softya(ソフト屋) » 6年前

もしかして「デバッガを使う」と言う意味が理解されていないのでは?と思いました。
「太田研究室 > Visual C++ 2010 Express プログラミング入門」
http://cvwww.ee.ous.ac.jp/vc10prog.html#7
ここの、「プログラムのデバッグ実行」をお読みください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#7

投稿記事 by sozai » 6年前

>softya様
デバッガの使い方ありがとうございます。
確認したところ、毎フレーム呼び出されているようで、デバッグなしで実行したところ、ぶつかったら、Game Over になりました。
ありがとうございます。
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#8

投稿記事 by softya(ソフト屋) » 6年前

デバッグなしで実行したら正常に動いて、デバッグありの場合は正常動作しないのなら、何か別のバグが有りますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#9

投稿記事 by sozai » 6年前

>softya様
返信遅れてすみません。
前述の通り、ゲームオーバーにはなるのですが、
なぜか縦に動く敵がちょうど一周目にプレイヤーが操作するアイコンとぶつからなければゲームオーバーになりません。
他にも色々あるのですが説明が難しいので、省略します。
要約すると、『二回目以降当たり判定が動作しない』ということになります。
エラーは一切出てこないので、コードに問題があるのだと思います。
原因としてはどんなものが挙げられそうですか?
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#10

投稿記事 by softya(ソフト屋) » 6年前

それこそデバッガで、変数とかの情報を確認してなぜ条件をすり抜けるか調べるべきですね。
提示されているコードだけだと動くんじゃないでしょうか?って感触しかありません。
No: 2で書いたようにif文を分解しないと調べづらいかもしれません。

【補足】
デバッグ方法で分からない事は聞いてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#11

投稿記事 by sozai » 6年前

早速で申し訳ないのですが、当たり判定などの瞬間的に処理される場合、その都度タイミングを合わせてブレークポイントを指定するのですか?
[hr]
Is it true?
Function = a==b;

アバター
Tatu
記事: 445
登録日時: 9年前
住所: 北海道

Re: 当たり判定の動作

#12

投稿記事 by Tatu » 6年前

日記(http://dixq.net/forum/blog.php?u=1264&b=3958)で公開されていたコードを見てみました。

当たり判定をうまく行えないのは敵のy座標が増えっぱなしになっているからではないでしょうか。

描画の時は剰余演算子%を使ってごまかしているから正常であるように見えるだけなのでしょう。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#13

投稿記事 by softya(ソフト屋) » 6年前

その瞬間を再現しやすいようにプログラムを一時的に直した方が良いと思います。
つまり、動き出した瞬間に衝突するようにするのです。

あとprintfDxを使って変数の内容を表示しても良いと思います。

> 当たり判定をうまく行えないのは敵のy座標が増えっぱなしになっているからではないでしょうか。

見逃してました。それでしょうね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#14

投稿記事 by sozai » 6年前

起動した瞬間、当たり判定が動くように下の画像のようにしたのですが、条件式が真になりません。
添付ファイル
画像.jpg
画像.jpg (52.44 KiB) 閲覧数: 2188 回
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#15

投稿記事 by softya(ソフト屋) » 6年前

この瞬間の条件式に出てくる変数をprintfDXで表示してみては?
あと条件式を変えていたら最新のもの提示してください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 当たり判定の動作

#16

投稿記事 by みけCAT » 6年前

printfDxなどで、
x_Draw,x_e1,y_Draw,y_e1,((x_Draw-x_e1)*(x_Draw-x_e1)+(y_Draw-y_e1)*(y_Draw-y_e1)),((75+13)*(75+13)),
((x_Draw-x_e1)*(x_Draw-x_e1)+(y_Draw-y_e1)*(y_Draw-y_e1))<=((75+13)*(75+13))
の値をリアルタイムで調べられますか?
運が悪いと、最適化で壊されているかもしれません。(レアケースですが、前に1度やられたことがあります)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#17

投稿記事 by sozai » 6年前

まだprintfDxで表示していないのですが、
奇妙なことにブレークポイントをいったん全てはずして続行を押したら数秒後GameOverのメッセージボックスが表示されメニューに戻りました。
ブレークポイントをはずす前までは条件式の値は偽だったはずなのですが...
[hr]
Is it true?
Function = a==b;

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 当たり判定の動作

#18

投稿記事 by みけCAT » 6年前

数秒後ということは、当たりと判定される範囲がおかしいかもしれません。
「条件式の値は偽」という情報は、画面に表示されていますか?
毎フレームブレークポイントで止まっていて、「当たる」部分に行っていなかった可能性があると感じました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#19

投稿記事 by sozai » 6年前

ひとまず、条件式をprintfDxで表示したら『62500+4900<=7225』と出ました。
[hr]
Is it true?
Function = a==b;

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#20

投稿記事 by sozai » 6年前

立て続けにすみません。

コード:

    x_de1 = (x_Draw-x_e1);
    x_de2 = (x_Draw-x_e2);
    y_de1 = (y_Draw-y_e1);
    y_de2 = (y_Draw-y_e2); 

    printfDx("%d+%d<=%d",x_de1*x_de1,y_de1*y_de1,85*85);
    if( x_de1*x_de1+y_de1*y_de1<=(75+13)*(75+13) ) {
	   GameOverFlag=true;
    }else if( x_de2*x_de2+y_de2*y_de2<=(75+10)*(75+10) ) {
	   GameOverFlag=true;
    }
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#21

投稿記事 by softya(ソフト屋) » 6年前

printfDxしている数値で85*85じゃなくて88*88だと思いますが、それを置いておいても条件を満たすはずがないですよね?
x_de1*x_de1がなぜ62500なのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#22

投稿記事 by sozai » 6年前

コード:

printfDx("x_de1=%d\tx_de1^2=%d\n",x_de1,x_de1*x_de1);
を追加してもう一度実行したところ、
『62500+4900<=7744』
『x_de1=-250[tab=10]x_de1^2=62500』
と表示されました。
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#23

投稿記事 by softya(ソフト屋) » 6年前

私が聞きたいのは、x_Draw-x_e1が-250となってしまう初期値と言うか状況です。
意図した通りなのですか?

デバッグとは、頭のなかの動作イメージと実際の動作を比べて問題点を探し出すことにあります。
なので、頭のなかにこういう値になるはずというイメージがないとデバッグは出来ません。
逆に言えば、そのイメージ無しに出来たプログラムは実は自分でもよく分かっていないプログラムってことになります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 当たり判定の動作

#24

投稿記事 by みけCAT » 6年前

もしかして、(x|y)_Drawとか(x|y)_e1は画像の左上の座標ですか?
でしたら、条件式中の変数の代わりに、その変数に該当する画像の半径を足した値を使ってください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#25

投稿記事 by sozai » 6年前

>softya様
ソースコードを確認したところ、誤ってx_Drawが0で初期化されていましたので直したのですが、x_de1はいまだに-250のままです。
何が起きているのかさっぱりです。
みけCAT さんが書きました:もしかして、(x|y)_Drawとか(x|y)_e1は画像の左上の座標ですか?
でしたら、条件式中の変数の代わりに、その変数に該当する画像の半径を足した値を使ってください。
>みけCAT様
x_Drawが0の時アイコンは右半分しか表示されないのでそうではないのだと思います。
[hr]
Is it true?
Function = a==b;

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 当たり判定の動作

#26

投稿記事 by みけCAT » 6年前

x_Drawとx_e1の値はそれぞれどうなっていますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#27

投稿記事 by softya(ソフト屋) » 6年前

x_Drawとx_e1もそれぞれ表示してみましょう。それは意図した値ですか?
デバッグとは、自分のやった事に疑い持ち、思い込みを排除するために色々と調べる事です。
こうなるはずだ → そうならない → 実は思い違い
と言うことです。
自分のやったこと全てを疑ってください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#28

投稿記事 by sozai » 6年前

当たり判定が動作するようになりました。
原因はおそらく、条件式を含む関数を二回呼び出していたことだと思います。

コード:

void Stage1(){
    
    The_Func();
    Other_Func();
    Draw_enemy();
    GameOverIF();
    if(GameOverFlag)  GameOver();

    if(Key[ KEY_INPUT_SPACE ]>=1){
	   Scene = eScene_Menu;
    }
}

コード:

bool GameOverFlag=false;

void GameOver_IF(){

    int x_de1,x_de2;
    int y_de1,y_de2;
    x_de1 = (x_Draw-x_e1);
    x_de2 = (x_Draw-x_e2);
    y_de1 = (y_Draw-y_e1);
    y_de2 = (y_Draw-y_e2); 

    printfDx("%d+%d<=%d\n\n",x_de1*x_de1,y_de1*y_de1,88*88);
    printfDx("x_de1=%d\tx_de1^2=%d\n\n",x_de1,x_de1*x_de1);
    printfDx("x_Draw=%d\tx_e1=%d\n\n",x_Draw,x_e1);
    if( x_de1*x_de1+y_de1*y_de1<=(75+13)*(75+13) ) {
	   GameOverFlag=true;
    }else if( x_de2*x_de2+y_de2*y_de2<=(75+10)*(75+10) ) {
	   GameOverFlag=true;
    }

}

コード:

void The_Func(){

//**********************************/
//色々な処理                          /
//                                         /
//**********************************/

    GameOver_IF();

    
}
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#29

投稿記事 by softya(ソフト屋) » 6年前

少なくも関数の構成が分かりづらいことが原因だとは理解しました。
ただ、提示されたコードでは、2回呼んでも大丈夫なはずです。

で、関数の構成はこちらを参考に直されたほうが良いですよ。
「新・C言語 ~ゲームプログラミングの館~ [DXライブラリ]」
http://dixq.net/g/
d.1 メイン関数の作り方
d.2 複数のファイルにわけてコンパイルする
d.3 ゲームの設計と分割コンパイル(1)
d.4 ゲームの設計と分割コンパイル(2)
d.5 ゲームの設計と分割コンパイル(3)
d.6 管理部の作り方 (似た要素のまとめ方)
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#30

投稿記事 by sozai » 6年前

Tatu さんが書きました: 当たり判定をうまく行えないのは敵のy座標が増えっぱなしになっているからではないでしょうか。

描画の時は剰余演算子%を使ってごまかしているから正常であるように見えるだけなのでしょう。
>Tatu様
ありがとうございます。
遅すぎるとは思いますが、やっと仰ることの意味がわかりました。
次のようにコードを訂正しました。

コード:

void Draw_enemy(){

	   DrawRotaGraph(x_e1,y_e1,1.0,0.1,E_Load.teki_1,TRUE);
	   DrawRotaGraph(x_e2,y_e2,1.0,0.0,E_Load.teki_2,TRUE);
	   
	   y_e1 += 2; 
	   y_e2 += 4;
	   y_e1 =  y_e1%480;
	   y_e2 =  y_e2%480;
}
[hr]
Is it true?
Function = a==b;

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#31

投稿記事 by sozai » 6年前

>softya様
わかりました。
では、そのサイト等を参考に一度、リファクタリングなどを行ってみます。
[hr]
Is it true?
Function = a==b;

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: 当たり判定の動作

#32

投稿記事 by softya(ソフト屋) » 6年前

リファクタリング後でも良いですけど、一度全部のコードを圧縮して添付してもらったほうがアドバイスが出来そうです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

sozai
記事: 57
登録日時: 6年前
住所: 日本-関東
連絡を取る:

Re: 当たり判定の動作

#33

投稿記事 by sozai » 6年前

>softya様
わかりました。では、次に書く日記に添付します。

当たり判定が動作しなかった原因はやはり、
座標が増加し続けるようだったので、そこのコードを訂正したら常に条件を満たせば動作するようになりました。
皆様、本当にありがとうございました。
[hr]
Is it true?
Function = a==b;

閉鎖

“C言語何でも質問掲示板” へ戻る