ページ 11

カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月03日(日) 04:48
by ウーパールーパー山田
半年ぶりにC言語を触る初心者です
DXライブラリを使っています

マウスカーソルでゲーム画面内のメニューボタンをクリックするまでを実装したいのですがしっくりくる方法が思いつきません
今考えている方法は

コード:

/*Mouse.cpp*/
void MouseCheck(); //マウスポインタの現在位置とマウスボタンの押下状態を調べる
bool MouseReturn(); //マウスボタンの押下状態を返す
bool MouseHitCheck(int ボタンの大きさ); //マウスポインタとメニューボタンの当たり判定をする
main関数で毎フレームごとにMouseCheck()を呼び出します
menu.cppにてMouseReturnを呼び出し、マウスボタンが押下されていたらMouseHitCheckに
メニューボタンの大きさを渡してメニューボタンの上でクリックされているのかどうかを調べます
メニューボタンは一つではないので全てのメニューボタンと当たり判定するまでループ処理させます

ここまで考えたのですがなんとなくスマートではない気がするのです
この処理はゲームの難易度を選択する画面で使いたいのですが
この先、同じように何かを選択する画面を実装させたいと思っています
そういったときにわざわざMouseReturnを呼び出してMouseHitCheckをループさせるというのは
何とも手間がかかった作業に見えるのです

今、自分が思いつく範囲ではこれが限界なので何かヒントを教えてもらえたら嬉しいです
よろしくお願いします

Re: カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月04日(月) 00:05
by THムラオサ
こんばんは私も初心者なので深くまでかけませんが以下のものを参考にして頂いたら幸いでございます。

「マウスカーソルでゲーム画面内のメニューボタンをクリックするまで」ということでバラして考えてみました。

1.マウスカーソルについて
    マウスカーソルの表示は

コード:

SetMouseDispFlag( TRUE );
でできます。

2.ゲーム画面のメニューについて
これは人によって作り方が色々違うと思いますがイメージ的には
MENU

ゲームスタート

終わり

なのでこれをDrawStringを使用し文字列で書きます。

イメージ的には
DrawString(x座標,y座標,表示させたい文字列←今回はゲームスタート,)
DrawString(x座標,y座標,終わり,)

3.クリックについて
言い換えれば当たり判定のことなんで
マウスの座標を読み込むようにしたいです!
マウスカーソルの座標を取得するには,GetMousePoint 関数使用
ということで     int GetMousePoint( int *XBuf, int *YBuf );を使えばいいかと。
XBuf, YBuf にはマウスカーソルの座標が代入されます

つぎに当たり判定について
文字列を四角形として,マウスカーソルを点とします.マウスカーソル
が文字列内にあるかどうかは,点が四角形内に存在しているかどうかの判定とな
ります.ここで,点の座標を(x1; y1), 四角形の左端の座標を(x2; y2), 高さをheight, 横幅を
width とすると
x1 x2
x1 x2 + width
y1 y2
y1 y2 + height
を満たせば,点が四角形内にあると判定できます
イメージ的には

コード:

//指定したボックス内にマウスが存在するかどうか
 //戻り値1:存在する0:存在しない
 int isContainMousePointer(int x, int y, int width, int height)
 {
 int mouseX, mouseY;
//マウスの座標を取得
 GetMousePoint( &mouseX, &mouseY );

 //ボックス内にマウス座標が存在するか
 if( (mouseX >= x && mouseX <= x + width) &&
 (mouseY >= y && mouseY <= y + height) ) {
 return 1;
 }
 return 0;
}
でいいかと

私が考えたのはこんなかんじです
参考にしてみてください。

Re: カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月05日(火) 03:42
by ISLe
GUIのシステムで、イベントプロシージャとかリスナーとかいうものをご存知ですか?
「コールバック」がヒントになると思います。

メニューボタンマネージャを作って、メニューボタンを登録して、
メニューボタンがどう振る舞うかは、メニューボタンマネージャが教えてやる仕組みです。

メニューボタンの振る舞いとは、例えば
マウスカーソルが上にあるかどうかで見た目が変わるとか、
マウスボタンが押されたときに見た目が変わるとか、
マウスボタンでクリックしたら何かが起きるとか、
です。

メニューボタンマネージャとメニューボタンが分かれていると何が良いかというと
もしキーボードでメニューを選択できるようにしたくなったときでも
メニューボタンのボタンとしての振る舞いは何も変わらない(変える必要がない)ので
メニューボタンマネージャをいじるだけで済みます。

メニューボタンに対して、マウスカーソルがいま上にあるよ、と嘘を教えてやれば
キーボードのカーソルキーで選択肢が移動しているように見えるし、
メニューボタンに対して、マウスボタンが押されたよ、と嘘を教えてやれば
キーボードのエンターキーで選択することもできるというわけです。

Re: カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月05日(火) 13:33
by ウーパールーパー山田
ご返信ありがとうございます

>>THムラオサさん
当たり判定関数の中でマウスの座標を取得するのは良いのでしょうか?
メニューボタンが複数ある場合、それぞれの当たり判定をするたびにマウスの座標を取得するのは無駄ではないのでしょうか?
ただ、今回のは例であって分かりやすさ優先で書いてくださっているのであれば、ごめんなさい
それと私も初心者ですので何か間違ったことを吐いてしまっている場合もごめんなさい

>>ISLeさん
「コールバック」を調べたら「コールバック関数」がでてきたのでそれを読んできましたがこれで良かったでしょうか?
それとメニューボタンを「登録して」、という部分と、メニューボタンマネージャが「教えてやる」仕組み、という部分が
よく分からないのでC言語ではどういう機能を使えばよいか詳しく教えてもらえませんか


今思ったんですけどそれぞれのボタンの大きさを構造体配列にまとめて当たり判定関数に渡してやれば
呼び出し側では、当たり判定関数の呼び出しの一行だけで済むのでこれでも良いのでしょうか

Re: カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月06日(水) 18:26
by ISLe
コールバックは、コールバック関数を呼び出してもらう、というのは利用者側の視点で
コールバック関数を呼び出す側からしたら、ふつうに関数を呼び出すだけのことです。
なにも特別な機能は使いません。

ボタンを管理する仕組みを作るというのは、利用者視点ではなく提供者視点でプログラムを作ることなので。
ウーパールーパー山田 さんが書きました:今思ったんですけどそれぞれのボタンの大きさを構造体配列にまとめて当たり判定関数に渡してやれば
呼び出し側では、当たり判定関数の呼び出しの一行だけで済むのでこれでも良いのでしょうか
構造体にはボタンのフォーカス状態やらのフラグも含めておいて
おっしゃるように構造体配列の各要素ごとにマウスカーソル座標との重なり判定とか
フォーカスが移動したとかの状態変化とか
構造体の内容に応じて描画するとか
というイベント等に対応したプロシージャ関数を呼び出す方法が一般的です。

C言語の範疇だと自由度を上げようとすると複雑なコードを書かなければいけませんが
同じ形のボタンを並べるくらいはスマートに書けます。

C++を使えば見た目のまったく違うボタンを同列に扱うようなコードも簡単に書けます。

Re: カーソルで画面内のボタンをクリックさせたい

Posted: 2016年1月06日(水) 19:49
by Dixq (管理人)
ゲームプログラミングの館にボタンの実装方法を紹介しています。
http://dixq.net/g/s_03.html
Androidで行っている処理と同じような作りにしてみました。