【ゲーム制作】マウス入力を取得する方法【C++】|クリック判定と座標の取り方

ゲーム制作

今回は、ゲーム制作でよく出てくる「マウス入力を取得する方法」について解説していきます。

「マウスのクリックってどう取るの?」
「カーソルの座標を知りたい…」
「クリックした場所に弾を撃ちたいけど、判定がズレる…」

こんな疑問はありませんか?

マウス入力は、UIボタンのクリックやシューティングの照準など、ゲームで欠かせない操作です。キーボード入力と同じく、Windowsなら数行で取得できます(キーボード入力を取得する方法の記事もあわせてどうぞ)。

この記事を読み終えると、あなたはマウスのクリック判定・カーソル座標の取り方・座標変換・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

マウス入力の基本

Windowsでは、<Windows.h> の関数を使ってマウス入力を取得します。よく使うのは次の2つです。

  • GetAsyncKeyState … ボタンが押されているか(左は VK_LBUTTON
  • GetCursorPos … カーソルの座標を取得

クリック判定を取る

左クリックされているかは、GetAsyncKeyState(VK_LBUTTON)最上位ビット& 0x8000 で調べます。

#include <iostream>
#include <Windows.h>

int main() {
    // 左ボタンが今押されているか
    if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) {
        std::cout << "左クリック中n";
    }
    // 右ボタンは VK_RBUTTON
    if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) {
        std::cout << "右クリック中n";
    }
    return 0;
}
左クリック中

ビット演算の & 0x8000 は「そのビットが立っているか」の判定です。このあたりはキーボード入力とまったく同じ考え方です。

カーソルの座標を取る

座標は GetCursorPos で取得できますが、これは画面全体(スクリーン)の座標です。ゲームウィンドウ内の座標にするには ScreenToClient で変換します。

#include <iostream>
#include <Windows.h>

void ShowMousePos(HWND hwnd) {
    POINT pt;
    GetCursorPos(&pt);          // スクリーン座標
    ScreenToClient(hwnd, &pt);  // ウィンドウ内の座標へ変換

    std::cout << "マウス: (" << pt.x << ", " << pt.y << ")n";
}
マウス: (320, 240)

これで、クリックした位置に弾を撃つ、UIボタンの上にカーソルがあるか判定する、といった処理が書けます。当たり判定はAABBの当たり判定の記事と組み合わせると便利です。

【重要】私が実際にマウス入力で困った体験談

個人開発でクリック位置に弾を撃つ処理を作ったとき、GetCursorPos の座標をそのまま使ったら、画面の左上ほど大きくズレて、狙った場所に弾が飛ばないという不具合にハマりました。

原因は、GetCursorPos が返すのはスクリーン座標で、ウィンドウの位置ぶんだけズレていたこと。ScreenToClient でウィンドウ座標に変換したら、ピタッと狙った場所に飛ぶようになりました。「マウス座標は ScreenToClient で変換」と体で覚えた出来事です。

マウス入力使用時のよくある失敗例と対処法

①スクリーン座標とウィンドウ座標の混同

体験談のとおり、変換しないとズレます。ゲーム内の判定には ScreenToClient でウィンドウ座標に直しましょう。

②「押した瞬間」を取れない

& 0x8000 は「押されている間ずっと真」です。押した瞬間だけ反応させたいなら、前フレームの状態と比べて「前は押していない→今押している」で判定します。

③ビット判定を忘れて常に真になる

if (GetAsyncKeyState(VK_LBUTTON)) のように & 0x8000 を忘れると、意図しない挙動になります。必ずビットで判定しましょう。

注意点

  • 座標はゲーム内で使う前に ScreenToClient で変換する
  • 「押した瞬間」は前フレームとの比較で取る
  • ここではWindows APIを使用。DirectXやSDLでは別の入力方法もある

まとめ

  • クリックは GetAsyncKeyState(VK_LBUTTON) & 0x8000 で判定
  • 座標は GetCursorPosScreenToClient で取る
  • スクリーン座標とウィンドウ座標の変換忘れに注意
  • 「押した瞬間」は前フレームと比較して判定する

マウス入力が取れると、ゲームの操作性が一気に広がります。まずはクリック判定とカーソル座標から、UIやシューティングに組み込んでみてください。

関連記事