【DxLib】で作るとき、必要最低限のおまじない（ウィンドウとキー入力）

# 概要
懐かしい気持ちになりつつ、DxLibでゲームを作ると最初に必ず必要となる要素をまとめたいと思います。
大本は大学のころに書いていたコードを見ながらまとめます。
プロジェクトの作成・設定とかファイルの生成とかは省きます。


# ウィンドウ生成回り
最初はmain.cppを作り、ウィンドウを作るためにWinMainの中でごちゃごちゃ書くかと思います。
プロジェクトのたびに書く必要がありますし、書き方では見にくくなってしまうので関数等でまとめちゃいましょう。
<details><summary>main.cpp</summary><div>

```cpp
#include "DxLib.h"
#include <string>


/// --------------------------------------------------------------------------------------------------
// ウィンドウサイズを決める
int winWidth = 0;
int winHeight = 0;
int bitColor = 0;

/// --------------------------------------------------------------------------------------------------
bool Init(const int t_winWidth, const int t_winHeight, const int t_bitColor, std::string t_projectName, bool t_fullScreen)
{
	winWidth = t_winWidth;
	winHeight = t_winHeight;
	bitColor = t_bitColor;

#ifdef _DEBUG
	SetOutApplicationLogValidFlag(TRUE);	// ログテキスト出力する
#elif NDEBUG
	SetOutApplicationLogValidFlag(FALSE);	// ログテキスト出力しない
#endif

	SetWindowText(t_projectName.c_str());		// メインウインドウのウインドウタイトルを変更する
	SetBackgroundColor(0, 0, 0);				// 背景色を変更
	ChangeWindowMode(TRUE);						// ウィンドウズモードにさせる

	if (t_fullScreen)
	{
		SetGraphMode(winWidth, winHeight, bitColor);			// 画面サイズ設定
		GetDefaultState(&winWidth, &winHeight, &bitColor);		// デフォルトウィンドウ値を得る
		SetWindowSize(winWidth, winHeight);			// デフォルトウィンドウサイズに合わせてゲームサイズを変更
	}

	// ＤＸライブラリ初期化処理
	if (DxLib_Init() == -1)
	{
		return false;			// エラーが起きたら直ちに終了
	}

	SetDrawScreen(DX_SCREEN_BACK);	// 背景描画

	return true;
}



/// --------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	if (!Init(640, 480, 32, "qiita", false)) return -1;	// ・ウィンドウサイズは640×480

	SetFontSize(64);

	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())
	{
	}

	// 削除
	DxLib_End();		// DXライブラリの後始末

	return 0;
}
```
</div></details>

画面サイズをグローバルで用意した理由としては、2Dの当たり判定で利用することもあるからです。
あとは、WinMainのクラス変数宣言してwhileでぐるぐる回せばいいかと思います。


# キー入力と終了キー
軽く書きます。ゲームパッドは少しややこしいのでキーボードのみです。
必要最低限ゲームを遊べるためにキー入力を行うかと思います。
また、Escキーでゲームを終了できるようにするかと思います。（これは自論です。）
ということで専用クラスを作成して用意しましょう。
<details><summary>KeyInput.h</summary><div>

```cpp
#pragma once

namespace input
{
	namespace key
	{
		class KeyInput
		{
		private:
			// キーボードの入力状態
			static int m_key[256];		// キーの入力状態格納用変数
			static char m_tmpKey[256];	// 現在のキーの入力状態を格納する

		public:
			static void InitKey();

			static void UpDate();

			static const int& Get(const int& t_keyCode);

			static const bool IsCheckEnd();
		};
	}
}
```
</div></details>

<details><summary>KeyInput.cpp</summary><div>

```cpp
#include "KeyInput.h"
#include "DxLib.h"

namespace input
{
	namespace key
	{
		int KeyInput::m_key[256];		// キーの入力状態格納用変数
		char KeyInput::m_tmpKey[256];	// 現在のキーの入力状態を格納する


		void KeyInput::InitKey()
		{
			for (int i = 0; i != 256; ++i)
			{
				m_key[i];
				m_tmpKey[i];
			}
		}
		void KeyInput::UpDate()
		{
			// 全てのキーの入力状態を得る（押されたら１を出力し、押されていなかったら０を返す
			if (GetHitKeyStateAll(m_tmpKey) == -1) return;


			// 全キー入力処理
			for (int i = 0; i < 256; ++i)
			{
				// 押されていなかったら
				if (m_tmpKey[i] == 0)
				{
					if (m_key[i] < 0)
					{
						m_key[i] = 0;
					}
					else if (m_key[i] > 0)
					{
						m_key[i] = -1;
					}
				}
				// i番のキーコードに対応するキーが押されていたら
				else if (m_tmpKey[i] == 1)
				{
					m_key[i]++;
				}
			}
		}
		const int& KeyInput::Get(const int& t_keyCode)
		{
			return m_key[t_keyCode];
		}
		const bool KeyInput::IsCheckEnd()
		{
			return m_key[KEY_INPUT_ESCAPE] > 0;
		}
	}
}
```
</div></details>

こんな感じで作れるかと思います。もっといい書き方ありそうですが…。

とりあえず、ここのIsCheckEndという関数で終了判定をとるようにしています。
これを先ほどのWinMainのwhileに追加させれば、どんな時でもEscを押されたらゲーム終了できるようになります。（安全かは置いといて）

それと変数を初期化するためにwhileの前にInitKeyを呼び出しておきます。
<details><summary>main.cpp</summary><div>

```cpp
#include "KeyInput.h"

<<<<<<<<<<<<<<<<<<<<<省略<<<<<<<<<<<<<<<<<<<<<

	input::key::KeyInput::InitKey();

	// ・どの画面でもescキーで終了
	while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen() && !input::key::KeyInput::IsCheckEnd())
	{
	}
```
</div></details>


# 終わりに
これで、必要最低限ウィンドウ生成してゲーム終了まで出来るようになったかと思います。
あとは、シーケンス用のクラス作ったりゲーム部分のクラス作り、先ほどのwhileでマイフレーム呼び出してもらうようにすればいいですね。