トップページ > 記事閲覧
画像の当たり判定
名前:C言語初心者 日時: 2022/12/12 12:25

DXライブラリで射的ゲームを作成しています。 的(画像)に当たり判定をつけて当たり判定の中でマウスの左クリックを押したら、画像が消える機能を作りたいのですが まだ未熟なもので実装の仕方がわからないので教えていただけると幸いです。よろしくお願いいたします。 #include "Game.h" #include "Scene.h" #include "DxLib.h" //画面遷移 void Game_Update() { if (CheckHitKey(KEY_INPUT_B) != 0) { //Bキーが押されていたら Scene_ChangeScene(eScene_Menu);//シーンをメニューに変更 } } //ゲーム void Game_Draw() { int targetGraph; int targetW, targetH; int MouseInput; int score = 0; int breakNum = 0; bool Flag = FALSE; int XPos = 0, YPos = 0; SetDrawScreen(DX_SCREEN_BACK); SetFontSize(20); DrawString(0, 0, "得点:", GetColor(255, 255, 255)); DrawFormatString(50, 0, GetColor(255, 255, 255), "%d", score); DrawString(110, 0, "破壊数:", GetColor(255, 255, 255)); DrawFormatString(190, 0, GetColor(255, 255, 255), "%01d", breakNum); DrawString(0, 450, "Bキーを押すとメニュー画面に戻ります。", GetColor(255, 255, 255)); // マウスを表示状態にする SetMouseDispFlag(TRUE); targetGraph = LoadGraph("image\\tg.png"); // 的のグラフィックのサイズを得る GetGraphSize(targetGraph, &targetW, &targetH); DrawGraph(40, 100, targetGraph, FALSE); DrawGraph(40, 200, targetGraph, FALSE); DrawGraph(40, 300, targetGraph, FALSE); while (ProcessMessage() == 0) { // マウスのキー入力状態取得 MouseInput = GetMouseInput(); //左クリックチェック if ((MouseInput & MOUSE_INPUT_LEFT)) { Flag = true; //マウスの座標取得 GetMousePoint(&XPos, &YPos); } //右クリックチェック if ((MouseInput & MOUSE_INPUT_RIGHT)) { Flag = false; } // マウスの左クリックが的に当たっているか判定 if (Flag) { } // 裏画面の内容を表画面に反映 ScreenFlip(); } }
メンテ

Page: 1 |

Re: 画像の当たり判定 ( No.1 )
名前:通りすがり 日時:2022/12/12 14:49

なにはともあれ > 当たり判定 なる物をあなたが定義しないことには始まらないのでは. 例えば, 的の絵の形と概ね一致する円とか四角形みたいなのを用いればそれで事足りる話なのか それとも的の画像とピクセル単位で一致しているような判定を行う必要がある話なのか …次第で話が変わり得ると思う.
メンテ
Re: 画像の当たり判定 ( No.2 )
名前:たろう 日時:2022/12/12 20:14

こんにちは、 画像に見立てた四角をクリックすると(消えるかわりに)赤くなるように描いてみました。 求めているものとは違うかもしれませんが、考え方としては似たようなものになると思います 見当違いでしたら無視してくださいm(__)m #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ) ; SetAlwaysRunFlag( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ; int MI,XPos,YPos; int X=250,Y=250,SIZE=20;//画像の座標とサイズ while( ProcessMessage() == 0 ) { ClearDrawScreen(); MI=GetMouseInput();int CLK=(int)(MI&MOUSE_INPUT_LEFT);//マウスクリックの取得 GetMousePoint(&XPos,&YPos);//マウス座標の取得 int HIT=(int)(CLK&&(XPos<X+SIZE&&XPos>X-SIZE)&&(YPos<Y+SIZE&&YPos>Y-SIZE));//★★当たり判定★★ DrawBox( X-SIZE, Y-SIZE, X+SIZE, Y+SIZE, GetColor(255,255-(HIT*200),255-(HIT*200)),1);//画像表示 X++;if(X>500)X=0;//画像の移動 ScreenFlip(); } DxLib_End() ; return 0 ; }
メンテ
Re: 画像の当たり判定 ( No.3 )
名前:通りすがり 日時:2022/12/13 10:36

まず最初に > 当たり判定の中でマウスの左クリックを押したら、画像が消える という話の「当たり判定の中で」という条件が無い状態の物を作る というステップを経てみてはどうか. すなわち「(場所を問わず)クリックしたら画像が消える」である. ↓ これができたら,「消える」仕組みが「クリックした位置次第で」動くようにちょっと変えるだけだ. …っていう感じに2段階に問題を分けると取り組みやすい(というか,本当は何が分からないのかが分かりやすくなる)んじゃないかな,とか. --- 「消える」という話については, そもそも描画しなければ表示されることはない(つまり「消えている」)のだから, 「(ゲームの現状態を示すデータが)ある条件を満たしているときのみ描画する」と考えると分かりやすいであろう. 端的に言えば, if( XXX ){ 描画 } //条件XXXが真であるときしか描画しないぜ! という話. で,クリックされたときには XXX の評価結果が適切に変わるような処理を行えばよいということだ. すっごいわかりやすい例としては…… 上記の XXX の正体が単純に int XXX = 1; とかいう変数である場合かな. これなら,クリック時には XXX = 0; とすれば良いよね.
メンテ
Re: 画像の当たり判定 ( No.4 )
名前:C言語初心者 日時:2022/12/13 11:34

通りすがりさんコメントありがとうございます。 的の定義はここでしてます↓ targetGraph = LoadGraph("image\\tg.png"); 画像とピクセル単位で一致しているような判定を行いたいです。
メンテ
Re: 画像の当たり判定 ( No.5 )
名前:C言語初心者 日時:2022/12/13 11:38

たろうさんコメントありがとうございます。 参考にさせていただきます。
メンテ
Re: 画像の当たり判定 ( No.6 )
名前:C言語初心者 日時:2022/12/13 12:00

通りすがりさん2回目のコメントありがとうございます。 参考にさせていただきながら実装試みてみます!
メンテ
Re: 画像の当たり判定 ( No.7 )
名前:通りすがり 日時:2022/12/13 12:42

> 画像とピクセル単位で一致しているような判定を行いたいです 私はこのライブラリを知らない文字通りの「通りすがり」でしかないので, ライブラリが提供する機能でこれを簡単に実現できるのかどうかはわからないのだけど…… そんな無知な人が考える手っ取り早い方法は 「ピクセル単位の当たり判定用データを画像とは全く別に用意して,それをプログラムで読込んで使う」かな. 例えばpbm画像みたいな{手作業で内容を編集すること,データの具合を可視化すること,プログラムで読み込むこと}等が簡単な形のファイルを用いる. もちろんこういう方法だと 的の画像 tg.png と,この手作りな当たり判定用データとの間の整合性については自分自身で担保する!ということになるわけだけど, 逆に言えば「ここの箇所だけは画像の見た目と反して 当たる/当たらない ようにしたい」みたいな自由度がある…と言えるかな.
メンテ
Re: 画像の当たり判定 ( No.8 )
名前:たろう 日時:2022/12/13 14:50

ピクセル単位という事でしたらSoftImageを使うとよいと思います 画像「0001.png」は、透明部分のあるものを読み込んでください。 透明部分をクリックすると無反応ですが、何か描いてある部分をクリックすると 画面が赤くフラッシュして、そのドットが削れるようにしました 参考にならなかったらごめんなさいm(__)m (※普段使っていないので間違いがあるかもしれません) #include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ) ; SetAlwaysRunFlag( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ; int MI,XPos,YPos; int IMG = LoadSoftImage("0001.png"); int IMGw,IMGh;GetGraphSize(IMG,&IMGw,&IMGh); int CLK=0; while( ProcessMessage() == 0 ) { ClearDrawScreen(); MI=GetMouseInput();if(MI&MOUSE_INPUT_LEFT){CLK=1;}else{CLK=0;}//マウスクリックの取得 GetMousePoint(&XPos,&YPos);//マウス座標の取得 if(CLK) { int r,g,b,a;GetPixelSoftImage(IMG,XPos,YPos,&r,&g,&b,&a); if(a>0){DrawPixelSoftImage(IMG,XPos,YPos,0,0,0,255);DrawBox(0,0,500,500,GetColor(255,0,0),1);} } DrawSoftImage( 0,0, IMG ) ; ScreenFlip(); } DxLib_End() ; return 0 ; }
メンテ
Re: 画像の当たり判定 ( No.9 )
名前:C言語初心者 日時:2022/12/14 14:43

なんとかそれっぽいものができました。 アドバイスありがとうございました もう一つだけ質問させて下さい。 画像にはうまく判定が出来たのですが画像に左クリック長押しすると得点と的の破壊数が加算し続けてしまいます。 自分の理想では、左クリックが押した瞬間の判定で得点と破壊数を加算させたいんですけどうまく修正出来ません。 何度も質問してしまい大変申し訳ないのですが、教えていただくと幸いです。よろしくお願いいたします。 // 射的ゲーム void Game_Draw() { ChangeWindowMode(TRUE); SetAlwaysRunFlag(TRUE); SetDrawScreen(DX_SCREEN_BACK); int MI, XPos, YPos; int X = 250, Y = 250; //画像の座標 int X1 = 330, Y1 = 300; //画像の座標1 int X2 = 170, Y2 = 170; //画像の座標2 int SIZE = 45; // 当たり判定修正用 int targetGraph, targetGraph1, targetGraph2; int score = 0; // 得点 int breakNum = 0; // 破壊数 int W, H; int W1, H1; int W2, H2; // 的 targetGraph = LoadGraph("image\\tg.png"); targetGraph1 = LoadGraph("image\\tg.png"); targetGraph2 = LoadGraph("image\\tg.png"); // 的のグラフィックのサイズを得る GetGraphSize(targetGraph, &W, &H); GetGraphSize(targetGraph1, &W1, &H1); GetGraphSize(targetGraph2, &W2, &H2); while (ProcessMessage() == 0) { ClearDrawScreen(); // 裏画面を初期化 SetFontSize(10); DrawString(0, 0, "得点:", GetColor(255, 255, 255)); DrawFormatString(50, 0, GetColor(255, 255, 255), "%d", score); DrawString(120, 0, "破壊数:", GetColor(255, 255, 255)); DrawFormatString(200, 0, GetColor(255, 255, 255), "%d", breakNum); DrawString(0, 450, "Bキーを押すとメニュー画面に戻ります。", GetColor(255, 255, 255)); MI = GetMouseInput(); // マウスのボタンの押下状態を取得する int CLK = (int)(MI & MOUSE_INPUT_LEFT); // マウスクリックの取得 GetMousePoint(&XPos, &YPos); // マウス座標の取得 int HIT = (int)(CLK && (XPos<X + W && XPos>X - W + SIZE) && (YPos<Y + H && YPos>Y - H + SIZE)); // 的1個目の当たり判定 int HIT1 = (int)(CLK && (XPos<X1 + W1 && XPos>X1 - W1 + SIZE) && (YPos<Y1 + H1 && YPos>Y1 - H1 + SIZE)); // 的2個目の当たり判定 int HIT2 = (int)(CLK && (XPos<X2 + W2 && XPos>X2 - W2 + SIZE) && (YPos<Y2 + H2 && YPos>Y2 - H2 + SIZE)); // 的3個目の当たり判定 X++; if (X > 500)X = 0; // 的1個目の移動 X1++; if (X1 > 500)X1 = 0; // 的2個目の移動 X2++; if (X2 > 500)X2 = 0; // 的3個目の移動 if (HIT){ DeleteGraph(targetGraph); score += 100; breakNum += 1; } else if (HIT1){ DeleteGraph(targetGraph1); score += 100; breakNum += 1; } else if (HIT2){ DeleteGraph(targetGraph2); score += 100; breakNum += 1; } ScreenFlip(); // 裏画面の内容を表画面に反映 } }
メンテ
Re: 画像の当たり判定 ( No.10 )
名前:通りすがり 日時:2022/12/14 17:17

> int HIT = (int)(CLK && (XPos<X + W && XPos>X - W + SIZE) && (YPos<Y + H && YPos>Y - H + SIZE)); // 的1個目の当たり判定 ここは 「マウスボタンが押されていて,且つ,マウスカーソル位置が特定の範囲内にあるかどうか」しか見ていない. で,この HIT をそのまま用いて > if (HIT){ 得点増加等 } ということをやっているのだから,そのような動作になって当然. 「既に破壊された的については以降はこのような処理を行わない」といったような話にしたいのであれば, 「それぞれの的が生きているかどうか」というステータスを管理し,それを必要なところで処理条件として用いる必要があるだろう.
メンテ
Re: 画像の当たり判定 ( No.11 )
名前:通りすがり 日時:2022/12/14 17:41

…というわけで, 「的が生きているかどうか」という情報を追加し, if( 的が生きているなら ){ この的についてどうのこうの } とか書くことを考えてみれば良いんじゃないかな. > 押した瞬間の判定で というのが, 「これって,要は,マウスボタンはずっと押しっぱなしにしとけばいいよね」 みたいなことにはしたくない,というような話なのであれば 「ボタンが押されているか」ではなくて「押した瞬間」というのを明確に判定する必要があるだろう. 「前回は押されてなかった,且つ,今は押されている」みたいな. その他のSuggestion : ・「これでいける」となるまでの試行錯誤は,「的1個」でやればどうか.(OKかどうかわからんコードを常に3セット書くのは面倒でしょ) ・で,「同じものを複数個…」という話は,配列でも使うことを考えてはどうか.(3セット書くの面倒でしょ) ・全員が同じ画像を用いるならばそれは全員で共有すれば良いんじゃないかな,とか. ・「的」っていう構造体でも用意すると楽なんじゃないかな.(そのこと自体に学習コストが発生するようなら,直近は「楽」じゃないかもだが)
メンテ
Re: 画像の当たり判定 ( No.12 )
名前:C言語初心者 日時:2022/12/15 14:27

アドバイスありがとうございます。 試行錯誤してみます!
メンテ
Re: 画像の当たり判定 ( No.13 )
名前:通りすがり 日時:2022/12/16 11:20

こちらに移行した様子. ttps://teratail.com/questions/it0owlkejk5hc5 …っていうようなことは,ちゃんと示したほうがご自身のためにも良いと思うよ. というのは, 私はたまたまこことリンク先の側の両方を見ていたんだけど, 他の人もそうだとは限らないわけで,そしたら黙って場所を変えるとせっかくここで今相談に乗ってくれている人からの助力が打ち切りになるよね. (あえて味方を減らすことはないんじゃないかな.) 仮に,「以降」ではなくて,両方を並行的に使っていこうと考えてるならば,それは「マルチポスト」と呼ばれる行為になる. マルチポスト自体が場のルールで制限されていることもあるし, まともにハンドリングされないことが多いためにネガティブなイメージを持たれやすい行為でもあるので, そこらへんはしっかりと対応する必要があるよ.
メンテ
Re: 画像の当たり判定 ( No.14 )
名前:C言語初心者 日時:2022/12/19 09:58

ルールを把握せず投稿してしまい、大変申し訳ありませんでした。 次回から気を付けます。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存