2014年04月

ゲーム製作日誌 プログラム編 No.6-1 「マウスの入力検知の実装」

こんにちは。お久しぶりです。
前回は、プログラムでプレイヤーが操作するマウスの状態を検知する方法を解説しました。今回はそれをどのようにライブラリに組み込むかを模索していきます。


1、組み込み方について考える要素

 キーボード回と同様、まずはマウスの入力検知機能にどんな特徴が必要かを考えます。
 1点を除いて、前回と全く同じです。
 
  • 判定はある周期のタイミングで一気に行い、ライブラリ使用者にはその周期内の判定記録を教えてあげればよい

     マウスをものすごく短い時間内にカチカチ出来る人はいません。ですからマウス状態を調べる作業を頻繁に行う必要はないです。決められた一定の周期に沿って取得しておけば十分です。


  • ゲームライブラリはひとつでよい、ふたつもいらない

      判定をする人は、一人でよいです。そんな時に便利なのがシングルトンパターンであることは前回説明しました。

  • クラスと関わるのは、更新タイミングとキーの状態取得時のみ

     このキー判定クラスが、利用者と関わる必要があるのは大きく分けて二回です。更新タイミングとキーの状態取得時のみです。しかし、ここではクリック状態とカーソル位置を別々に受け取れるようにして3つの関数を用意することにします。
     希望に応じて、カーソルが範囲内にあるか判定する関数を用意してみるのも良いかもしれません。
    ///<summary>
    一定周期が経過しキーボード状態を取得するタイミング
    </summary>
    void Update();

    ///<summary>
    マウスカーソルを取得。
    </summary>
    void GetCursor(out int x, out int y);

    ///<summary>
    ボタンがクリックされているか取得。(返り値:ボタンが押されているか)
    </summary>
    bool IsPressed(int button);

2、絶対座標ではなくフォーム座標

 Windows APIで入手できたマウスカーソル座標とは、画面全体の中での座標でした。実際ゲームを作ってみるとその画面座標というものがいかに意味を成さないわかります。
 ゲームは、絵が表示されるウィンドウの上をポチポチクリックして進めていくものなので、画面全体での座標だけ知ってても全く使えないのです。その絵が表示されてるウィンドウから見たカーソル位置を知る必要があります。
 画面全体のカーソル座標からウィンドウ上のカーソル座標を計算するには、ウィンドウフォームのPointToClient()メソッドを使ってあげます。チョー簡単ですね。ここのところは、サンプルにも入れておいたので気になる方はそちらを参照ください。

ClientPosition



3、サンプルプログラム

 今回の内容を元にサンプルプログラムを作ってみました。詳細はこちらを御覧ください。

 次回からは、ゲームライブラリの描画部にいよいよ入っていこうかなと思っています。(予定)


ゲーム製作日誌 プログラム編 No.6-2 サンプルプログラム

こんにちは。
 この記事では、ゲーム製作日誌 プログラム編 No.6「マウスの入力検知部分の実装」で考えたマウス判定処理のゲームライブラリへの組み込み方法を実現したソースコード例を紹介します。No.3で扱った、SharpDXの導入が前提になっています。
 今回のプログラムは、No.4のサンプルプログラムの状態更新部分を少し書き換えただけです。

/////////////////////////////////////////////////
//
// マウス入力判定機能クラス
//
// Author. ウマモサク
/////////////////////////////////////////////////

using SharpDX.DirectInput;
using System.Runtime.InteropServices;

class MouseInterface{
#region API連携
//GetCursorPosで現在座標を取得
[DllImport("user32.dll")]
private static extern void GetCursorPos(
ref tagPOINT lpPoint
);

//現在座標が入る構造体
public struct tagPOINT
{
public UInt32 x;
public UInt32 y;
}
#endregion

//シングルトン
private static MouseInterface instance;
public static MouseInterface Instance
{
get
{
return instance;
}
}
private static bool initialized=false;
public static void Initialize()
{
if (initialized)
return;

initialized = true;
instance = new MouseInterface();
}
public static void Dispose()
{
if (initialized)
{
instance.DisposeDevice();
instance = null;
initialized = false;
}
}

protected MouseInterface()
{
this.InitializeDevice();
}

private DirectInput directInput;
private Mouse device;

private MouseState buttonState;
private tagPOINT cursorState;

//描画フォーム
private System.Windows.Forms.Form screenForm;
public void SetScreenForm(System.Windows.Forms.Form form)
{
screenForm = form;
}

public void InitializeDevice()
{
directInput = new DirectInput();

//マウスが存在しない場合への対処
Guid keyboardGuid = Guid.Empty;
foreach (var g in directInput.GetDevices(DeviceType.Mouse, DeviceEnumerationFlags.AllDevices))
{
keyboardGuid = g.InstanceGuid;
}

if (keyboardGuid == Guid.Empty)
{
throw new Exception("マウスが見つかりません");
}

//デバイスを生成してマウス状態の取得を開始
device = new Mouse(directInput);
device.Acquire();

buttonState = device.GetCurrentState();
}

public void DisposeDevice()
{
device.Dispose();
directInput.Dispose();
}

public void Update()
{
buttonState = device.GetCurrentState();
cursorState = new tagPOINT();
GetCursorPos(ref cursorState);

//カーソル位置をフォーム座標に変換する
if (screenForm != null)
{
System.Drawing.Point p = new System.Drawing.Point((int)cursorState.x,(int)cursorState.y);
p = screenForm.PointToClient(p);
cursorState.x = (uint)p.X; cursorState.y = (uint)p.Y;
}
}

public bool IsPressed(int button)
{
return buttonState.Buttons[button];
}

public void GetCursor(out int x, out int y)
{
x = (int)cursorState.x;
y = (int)cursorState.y;
}
}


 以上が、ライブラリ部分です。このライブラリは、ゲーム起動時に以下のコードで初期化します。MouseInterfaceクラスの実体を作成するのです。

MouseInterface.Initialize();


 その後、一定周期で以下のコードを呼び出します。ゲームでは通常、メインループという一定周期で処理をする仕組みを持っているため、その中に記述すればOKです。

MouseInterface.Update();


 実際にボタン押下状況を取得するときは、以下の関数呼び出しの返り値から判断します。左ボダンの判定を例に挙げます。

MouseInterface.IsPressed(0)

 
 マウスカーソルの座標を取得するには、以下の関数呼び出しの引数郡から判断します。

int cursorX,cursorY;
MouseInterface.GetCursor(out cursorX,out cursorY);

 ゲーム終了時には、作成した実体を消去してデバイスを開放する必要があります。

ゲーム制作日誌グラフィック編No.2立ち絵その2

ストーリーに関わる重要人物の立ち絵です。
たぶん一番書き直した回数が多い人です。
とにかく真っ黒という注文でした。
デス

twitterはこちら
ニコ生放送します
ギャラリー
  • ウマモサク
  • ウマモサク
  • ウマモサク
  • 3/17 制作記録
  • 3/17 制作記録
  • C91告知
  • C91告知
  • C91告知
  • C91告知
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

  • ライブドアブログ