私がゲーム制作のときに自機を動かすときにつくるもの

:::note warn
コメント欄の方にありますが，色々と変な箇所がありました．
それに伴い，本記事，及び私のコードの方も修正いたしました．
:::

最初にゲーム制作を始めたころに，まず自機をどう動かすかとかで非常に悩んだので適当においておく．
きっと，もっと効率的に且つもっとわかりやすく書かれている方はたくさんいると思うので他の方のも参考にすることを非常に強くお勧めする．

# まずはクラスを作る

以下のような感じで$\texttt{player.h}$を作った：

```c++: player.h
#pragma once

#include <DxLib.h>
#include "core.h"

class player
{
private:
	char KeyBuf[_KEY_BUF_];						// キーボードのバッファ
	unsigned int m_player_image;

public:
	int velocity;								// 速度
	int X;										// 座標
	int Y;										// 座標

	/// <summary>
	/// 画像
	/// </summary>
	/// <param name="file_path">ファイルパス</param>
	void SetImage(const char* file_path);

	/// <summary>
	/// 自機を動かす関数
	/// </summary>
	void Move();

	/// <summary>
	/// 自機の描画
	/// </summary>
	void Draw();
};
```

そして$\texttt{player.cpp}$の中身は以下の様にした．
```c++: player.cpp
#include "player.h"

void player::SetImage(const char* file_path)
{
	player_image = LoadGraph(file_path);
}

void player::Move()
{
	GetHitKeyStateAll(KeyBuf);
    
	if (! KeyBuf[KEY_INPUT_LSHIFT]) // シフトを押していないときは通常移動
	{
		if (KeyBuf[KEY_INPUT_RIGHT])
		{
			X = X + velocity >= WIDTH_X ? X : X + velocity; // Velocity分だけ右に移動
		}
		if (KeyBuf[KEY_INPUT_LEFT])
		{
			X = X - velocity <= 0 ? X : X - velocity; // Velocity分だけ左に移動
		}
		if (KeyBuf[KEY_INPUT_UP])
		{
			Y = Y - velocity <= 0 ? Y : Y - velocity; // Velocity分だけ上に移動
		}
		if (KeyBuf[KEY_INPUT_DOWN])
		{
			Y = Y + velocity >= WIDTH_Y ? Y : Y + velocity; // Velocity分だけ下に移動
		}
	}
	else // シフトを押しているときは低速移動（移動速度半分）
	{
		if (KeyBuf[KEY_INPUT_RIGHT])
		{
			X = X + velocity / 2 >= WIDTH_X ? X : X + velocity / 2;
		}
		if (KeyBuf[KEY_INPUT_LEFT])
		{
			X = X - velocity / 2 <= 0 ? X : X - velocity / 2;
		}
		if (KeyBuf[KEY_INPUT_UP])
		{
			Y = Y - velocity / 2 <= 0 ? Y : Y - velocity / 2;
		}
		if (KeyBuf[KEY_INPUT_DOWN])
		{
			Y = Y + velocity / 2 >= Y ? WIDTH_Y : Y + velocity / 2;
		}
	}
}

void player::Draw()
{
	DrawExtendGraph(X - 15, Y - 15, X + 15, Y + 15, m_player_image, TRUE);
}
```

謎の``WIDTH_X``や``WIDTH_Y``などがあるが，これは$\texttt{core.h}$内で定義されているマクロで，それぞれウィンドウの幅と高さである．

```c++: core.h
#pragma once

#include <DxLib.h>

// 画面サイズ
#define WIDTH_X 640
#define WIDTH_Y 480

#define _KEY_BUF_ 256

/// <summary>
/// FPSを設定する関数
/// </summary>
/// <param name="">fps</param>
void FPS(int fps);

/*
core.cpp の中身：

#include "core.h"

void FPS(int fps)
{
	WaitTimer(1000.0 / fps);
}
*/
```

# 実際に動かしてみる

メイン関数には以下の様に書いてみた．

```cpp: main.cpp
#include <DxLib.h>

#include "core.h"
#include "player.h"

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	if (DxLib_Init() == -1)
	{
		return -1;
	}

	ChangeWindowMode(TRUE);							// ウィンドウモードに変更
	SetGraphMode(WIDTH_X, WIDTH_Y, 32);				// ウィンドウサイズの変更
	SetDrawScreen(DX_SCREEN_BACK);

    player Player;						// 自機
    Player.X = WIDTH_X / 2;				// 自機のX座標を中央に
    Player.Y = WIDTH_Y / 2;				// 自機のY座標を中央に
    Player.velocity = 4;				// 自機の移動速度の変更
    Player.SetImage("hoge.png");		// 画像の設定

	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0)
	{
         Player.Move();
         Player.Draw();

         FPS(60); // 60 fps
	}

	DxLib_End();
	return 0;
}
```

これを動かすと以下のアニメーションのようになる．
![bandicam 2025-01-01 17-18-17-218.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734379/023fead3-f0b1-4887-38e0-c72a008a3f66.gif)