【ゲーム制作】マウス入力を取得する方法【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 で判定
  • 座標は GetCursorPos + ScreenToClient で取る
  • スクリーン座標とウィンドウ座標の変換忘れに注意
  • 「押した瞬間」は前フレームと比較して判定する

座標は、GetCursorPosとScreenToClientで取ります。スクリーン座標とウィンドウ座標の変換を、忘れないでください。「押した瞬間」は、前のフレームの状態と比較して判定します。

関連記事