ゲームプログラミングの骨組み:その1「入力処理」

アバター
a5ua
記事: 199
登録日時: 14年前

ゲームプログラミングの骨組み:その1「入力処理」

投稿記事 by a5ua » 14年前

以前の日記では、キーボードの入力処理のみを扱いましたが、入力するデバイスは他にもありますよね。というわけで、
・キーボード
・マウス
・ジョイパッド
の3つの入力処理を扱うクラスを作成します。クラス名は、それぞれ、KeyboardState、MouseState、JoypadStateとします。

これらのクラスの機能は、ボタンが「押されているかどうか」、「押された瞬間かどうか」および「離された瞬間かどうか」を判定します。

それでは、クラスの定義を見てみましょう。

CODE:

#pragma once

namespace a5ua
{
	class KeyboardState
	{
	public:
		KeyboardState();

		void update();

		bool presses(int code) const;
		bool triggers(int code) const;
		bool releases(int code) const;

	private:
		char m_buffer[2][256];
	};

	class MouseState
	{
		/* 省略 */
	};

	class JoypadState
	{
		/* 省略 */
	};

	struct InputSet
	{
		KeyboardState key;
		MouseState mouse;
		JoypadState joypad;
	};
}
状態を更新する関数として、update()が用意されています。
「押されているかどうか」はpresses(code)で調べます。
「押された瞬間かどうか」はtriggers(code)で調べます。
「離された瞬間かどうか」はreleases(code)で調べます。
codeはDxLib.hに定義されている値を用います。

メンバ変数に、

CODE:

private:
	char m_buffer[2][256];
とありますが、要素数256の配列で1フレーム分の入力状態を格納できます。ここでは、2フレーム分の状態を必要とするので、このようなメンバ変数を定義しています。
MouseStateクラスでは、座標を取得する関数などもありますが、長くなるのでここでは省略します。
また、これらのクラスを、InputSetという構造体にまとめておきます。

ところで、皆さん。constメンバ関数はご存じですか?
上記で言うと、12行目の

CODE:

bool presses(int code) const;
などのことです。

constメンバ関数とは、オブジェクトの内部状態が変更されない関数のことです。つまり、constメンバ関数内では、メンバ変数の値が変更されないので、読み出し専用ということになります。(書き込もうとすると、コンパイルエラーになります。)

一方、10行目の

CODE:

void update();
は、constが付いていません。なので、update()内では、メンバ変数の変更が自由にできます。

constメンバ関数の必要性は、次のサンプルで説明します。

では、これらのクラスを使ったサンプルプログラムを見てみましょう。

CODE:

#include 

#include "InputSet.h"

// テスト用コード
namespace test
{
	// 位置、色を表す構造体
	struct point
	{
		int x;
		int y;
		int color;
	};

	// 位置を補正する
	void correct(int &v, int min, int max)
	{
		if (v < min) {
			v = min;
		}
		if (max <= v) {
			v = max - 1;
		}
	}

	// 位置を補正する
	void correct(point &p)
	{
		correct(p.x, 0, 640);
		correct(p.y, 0, 480);
	}

	// キーボード入力により上下左右に移動
	void move(point &p, const a5ua::KeyboardState &key)
	{
		if (key.presses(KEY_INPUT_LEFT)) {
			p.x -= 10;
		}
		if (key.presses(KEY_INPUT_RIGHT)) {
			p.x += 10;
		}
		if (key.presses(KEY_INPUT_UP)) {
			p.y -= 10;
		}
		if (key.presses(KEY_INPUT_DOWN)) {
			p.y += 10;
		}
	}

	// ジョイパッド入力により上下左右に移動
	void move(point &p, const a5ua::JoypadState &joypad)
	{
		if (joypad.presses(DX_INPUT_PAD1, PAD_INPUT_LEFT)) {
			p.x -= 10;
		}
		if (joypad.presses(DX_INPUT_PAD1, PAD_INPUT_RIGHT)) {
			p.x += 10;
		}
		if (joypad.presses(DX_INPUT_PAD1, PAD_INPUT_UP)) {
			p.y -= 10;
		}
		if (joypad.presses(DX_INPUT_PAD1, PAD_INPUT_DOWN)) {
			p.y += 10;
		}
	}

	// マウスカーソルの位置に合わせて移動
	void move(point &p, const a5ua::MouseState &mouse)
	{
		p.x = mouse.x();
		p.y = mouse.y();
	}
}

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
	ChangeWindowMode(TRUE);		// ウィンドウモードで起動

	SetMainWindowText(_T("ゲームプログラミングの骨組み:入力処理"));

	if (DxLib_Init() != 0) {
		return -1;
	}

	SetDrawScreen(DX_SCREEN_BACK);

	a5ua::InputSet input;

	test::point p[3] = {
		{100, 100, GetColor(255, 0, 0)}, 
		{200, 200, GetColor(0, 255, 0)}, 
		{300, 300, GetColor(0, 0, 255)}, 
	};

	while (ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		// 入力状態の更新
		input.key.update();
		input.joypad.update();
		input.mouse.update();

		// ESCキーで終了
		if (input.key.presses(KEY_INPUT_ESCAPE)) {
			break;
		}

		test::move(p[0], input.key);		// キーボードによる移動
		test::move(p[1], input.joypad);		// ジョイパッドによる移動
		test::move(p[2], input.mouse);		// マウスによる移動

		for (int i = 0; i < 3; ++i) {
			test::correct(p[i]);	// 位置補正
			DrawCircle(p[i].x, p[i].y, 30, p[i].color);
		}

		ScreenFlip();
	}

	DxLib_End();

	return 0;
}
注目して欲しいのは、以下の関数です。

CODE:

// キーボード入力により上下左右に移動
void move(point &p, const a5ua::KeyboardState &key)
{
	/* 省略 */
}
この引数keyは、constなオブジェクトへの参照となっています。つまり、keyはオブジェクトの状態を変化させることはできません。

CODE:

key.update();
などとすると、コンパイルエラーになります。なぜなら、update()は、constメンバ関数ではないからです。constなオブジェクトからは、constメンバ関数のみが呼び出せます。
ですから、

CODE:

key.presses(KEY_INPUT_LEFT);
などは問題なく呼び出せます。

update()はメインループの最初に1回だけ呼び出せばよいので、他の場所で呼ばれると困るわけです。

CODE:

test::move(p[0], input.key);
という関数呼び出しでは、input.keyの内部状態は変更されないことがわかるので、安心ですね。

このように、constメンバ関数を使うことにより、より健全なプログラミングが出来ます。

今回作成したサンプルプログラム(バイナリおよびソース)をアップロードしました。(ビルドにはDXライブラリが必要です。)
実行すると、キーボードで動かせる、ジョイパッドで動かせる、マウスで動かせるが表示されます。
http://www1.axfc.net/uploader/Sc/so/169009.zip&key=mixC
添付ファイル
ss.JPG
ss.JPG (18.06 KiB) 閲覧数: 0 回
最後に編集したユーザー a5ua on 2010年11月01日(月) 09:11 [ 編集 1 回目 ]

コメントはまだありません。