#はじめに
学校の制作を進める中で意外と多くの人から質問を受けたのでDXライブラリで疑似的にボタンを作ってみようと思います。
#処理の流れ
まず前提として無限ループの中でキー判定を行います。わからない方はキャラクターの移動(キー入力判定の作成)を見てもらえればと思います。
①左クリックの判定
↓
②マウスカーソルの位置を取得
↓
③画像との当たり判定
この3ステップで処理を作っていきます。
#①左クリックの判定
前回はCheckHitKey()
で入力判定を行ったと思いますが、マウスの場合はGetMouseInput()
という関数を使って入力判定を行います。
if (GetMouseInput() & MOUSE_INPUT_LEFT)
ここで見落としがちなのですが、&&ではなく***&***を使っています。つまり論理積によって入力されたキーを判定しています。まぁだからどうしたというところなんですが間違えると動かないので一応。
#②マウスカーソルの位置を取得
クリックしただけではボタンを押したのかどうか判定できませんのでカーソルの位置を取得する必要があります。ループ内で取得しておいてもいいのですがクリックしたとき以外はカーソル位置を使いませんのでクリックした後で取得するようにします。
int mouseX, mouseY;
GetMousePoint(&mouseX, &mouseY); // カーソルの位置を取得
2つの変数に値を格納必要があるので2つのint型変数のアドレスを渡しています。これでmouseX
とmouseY
にそれぞれカーソルのX座標とY座標が格納されます。
#③画像との当たり判定
ここまででマウスをクリックしたときにカーソルの位置を取得することができました。あとは画像の上でクリックしたかどうかを判定することでボタンのように見せることができます。
const int posX = 220; // 画像のX座標
const int posY = 190; // 画像のY座標
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ChangeWindowMode(TRUE);
SetWindowSize(640, 480);
SetBackgroundColor(255, 255, 255);
if (DxLib_Init() == -1)
return 0;
SetDrawScreen(DX_SCREEN_BACK);
// 画像読み込みとサイズ取得
int picX, picY;
int picImage = LoadGraph("button.png");
GetGraphSize(picImage, &picX, &picY); // 画像サイズ取得
DrawGraph(posX, posY, picImage, FALSE);
ScreenFlip();
このようにconst変数を使って画像を描画し、画像サイズを変数に読み込んでおくことで当たり判定が非常にやりやすくなりますし、変更も容易になるので少し脱線して紹介しておきます。
あとは先ほどまでに使ってきたものを組み合わせるだけですが、当たり判定について確認しておきます。
posX <= mouseX < (posX + picX)
かつposY <= mouseY < (posY + picY)
でマウスカーソルが画像上にあることを表現できます。ただ、2つの条件式をつなげることはできないので&&(AND演算子)
でそれぞれを結合して表現します。
#include "DxLib.h"
const int posX = 220; // 画像のX座標
const int posY = 190; // 画像のY座標
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ChangeWindowMode(TRUE);
SetWindowSize(640, 480);
SetBackgroundColor(255, 255, 255);
if (DxLib_Init() == -1)
return 0;
SetDrawScreen(DX_SCREEN_BACK);
// 画像読み込みとサイズ取得
int picX, picY;
int picImage = LoadGraph("button.png");
GetGraphSize(picImage, &picX, &picY); // 画像サイズ取得
DrawGraph(posX, posY, picImage, FALSE);
ScreenFlip();
while (!ProcessMessage()) {
if (GetMouseInput() & MOUSE_INPUT_LEFT) {
int mouseX, mouseY;
GetMousePoint(&mouseX, &mouseY); // カーソルの位置を取得
if (mouseX >= posX && mouseX < (posX + picX) && mouseY >= posY && mouseY < (posY + picY)) {
break;
}
}
}
return 0;
}
このプログラムでは表示されたボタンをクリックするとループから外れて終了します。
通常はbreak;
の部分を処理や関数呼び出しに置き換えることでボタンのような実装を行っています。
#ちょっとした小技
素材がうまく作れなかったのでソースは貼りませんが、クリックした感を出したければ
1. break;
をクリック後画像への張り替え処理と待ち処理に置き換える。
2. それから処理に移る。
これであたかもクリックしてから処理が行われたかのように見せられます。実際にはただのアニメーションを挟んだだけですがユーザーがクリックしたと認識することで「当たり判定とアニメーション」から**「ボタン」**になります。
#最後に
少し手抜きをした点はありますが、ボタンってこんな感じでも作れるんだと軽く考えてもらえればいいかと思います。CreateWindow関数
を使わなくてもボタン"のようなもの"は作れるので初めてGUIのゲームを作成する際などはこちらのほうが触れ合いやすくいいかと思います。