2Dゲーム制作㉑(2025/08/28-2025/09/01)

●クラス構成

main.cpp ⇒ Applicationクラス ⇒ SceneManagerクラス

                 main.cpp
                                     ↓
                                Applicationクラス
                   ↓
                               SceneManagerクラス
    ↓              ↓             ↓
  TitleSceneクラス      GameSceneクラス     GameOverSceneクラス
                   ↓
      ↓          ↓        ↓         ↓
  Playerクラス  PlayerBulletクラス  Enemyクラス  EnemyBulletクラス

Applicationクラスを作成(Application.h)
main.hから、ウインドウサイズの定数定義を移動。

#pragma once


class Application
{
public:
	static constexpr int WINDOW_WID = 800;	// ウィンドウの横サイズ
	static constexpr int WINDOW_HIG = 600;	// ウィンドウの縦サイズ
	//constexper ⇒ コンパイル時に値が確定されるので、実行が早くなる 
private:

};

クラスのメンバをpublic領域に記述する。

#pragma once

class SceneManager;	//既にあるクラスを「使用する」という意味合いの宣言

class Application
{
public:
	static constexpr int WINDOW_WID = 800;	// ウィンドウの横サイズ
	static constexpr int WINDOW_HIG = 600;	// ウィンドウの縦サイズ

	Application();		//コンストラクタ
	~Application();		//デストラクタ

	//constexper ⇒ コンパイル時に値が確定されるので、実行が早くなる 
	bool SystemInit(void);	//初期化処理
	void Run(void);			//ゲーム起動
	bool Release(void);		//解放処理(最後の一回のみ実行)

private:
	SceneManager* sceneM;	//SceneManagerクラスのインスタンスのポインタ(クラスを破棄するまで使える)

	void Update(void);		//更新処理
	void Draw(void);		//描画処理
};

空の関数を書いて中身を写していく。
まずはmain.cppのInit関数から初期化部分を移動。
次にRun関数の中身とDraw関数の中身を書いていく。
(Application.cpp)

#include<DxLib.h>
#include<stdio.h>
#include<time.h>
#include"Application.h"

//コンストラクタ
Application::Application(void) {

}

//デストラクタ
Application::~Application(void) {

}

//初期化処理(最初の一回のみ実行)
bool Application::SystemInit(void)
{
//-----------------
// システム設定
//-----------------
SetWindowText("2505889 ゆき");		// ウィンドウのタイトルの設定
SetGraphMode(WINDOW_WID, WINDOW_HIG, 32);	// ウィンドウのサイズと色モードの設定
ChangeWindowMode(true);				// ウィンドウの表示モード(true=ウィンドウモード/false=フルスクリーン)

int err = DxLib_Init();				// DXライブラリの初期化
if (err == -1)return false;

SRand((unsigned int)time(NULL));

}

void Application::Run(void)
{
	while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0) {
		Update();
		Draw();
}

void Application::Update(void)
{

}

void Application::Draw(void)
{
	SetDrawScreen(DX_SCREEN_BACK);
	CrearDrawScreen();

	ScreenFlip();
}

bool Application::Release(void)
{
	return true;
}

main.hに置いていた列挙型宣言をStDefine.hを作成して移植。
SCENE_KIND_NON = -1, を後で使うので追加しておく。
(StDefine.h)

#pragma once

//------------------
// 列挙型定数
//------------------
//シーンの種類
enum eSceneKind {
    SCENE_KIND_NON = -1,	//ゲーム開始時
	SCENE_KIND_TITLE,	//タイトルシーン
	SCENE_KIND_GAME,	//ゲームシーン
	SCENE_KIND_GAMEOVER,	//ゲームオーバー

	SCENE_KIND_MAX,		//
};

//ゲーム進行状況
enum eStageExitConditionsKind {
	ESTAGE_EXIT_NON = -1,			//戦闘中
	ESTAGE_EXIT_CLEAR,			//条件1:プレイヤーの勝利
	ESTAGE_EXIT_ENEMY_SHOT,			//条件2:敵弾がプレイヤーにヒット
	ESTAGE_EXIT_ENEMY_OCCUPATION,	//条件3:敵が最下段に到達

	ESTAGE_EXIT_KIND_MAX,
};

// 移動方向
enum eEnemyMoveDirection {
	ENEMY_DIR_NON = -1,	//方向設定がない場合
	ENEMY_DIR_RIGHT,	//0 :右方向
	ENEMY_DIR_LEFT,		//1 :左方向
	ENEMY_DIR_DOWN,		//2 :下方向

	ENEMY_DIR_MAX,		//
};

//接触している端の方向
enum eEnemyHitEdgeDir {
	ENEMY_HIT_EDGE_NON = -1,	//どの端にも接触していない
	ENEMY_HIT_EDGE_RIGHT,		//0:右方向
	ENEMY_HIT_EDGE_LEFT,		//1:左方向
	ENEMY_HIT_EDGE_DOWN,		//2:下端に接触

	ENEMY_HIT_EDGE_MAX,
};

シーン管理のためにSceneManager.hを作成
(SceneManager.h)

#pragma once

#include "StDefine.h"

class SceneManager
{
public:
	SceneManager(void);		//コンストラクタ
	~SceneManager(void);	    //デストラクタ

	bool SystemInit(void);	    //初期化処理(最初の一回のみ実行)
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool release(void);		//解放処理(最後の一回のみ実行)

private:
	eSceneKind scene_ID;	    //現在のシーンID番号

};

空の関数を書いていく。
コンストラクタとSystemInit()
(SceneManager.cpp)

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

//コンストラクタ
SceneManager::SceneManager(void)
{
	scene_ID = SCENE_KIND_NON;	//オブジェクト生成時のみに行われるため、数値の初期化は別関数で行う
}

//デストラクタ
~SceneManager::SceneManager(void)
{

}

bool SceneManager::SystemInit(void)
{
	scene_ID = SCENE_KIND_TITLE;

	return true;
}

//初期化処理(最初の一回のみ実行)
bool SceneManager::Update(void)
{

}

//描画処理
void SceneManager::Draw(void)
{

}

//解放処理(最初の一回のみ実行)
bool SceneManager::release(void)
{
	return true;
}

Application.h

#pragma once

class SceneManager;	//既にあるクラスを「使用する」という意味合いの宣言

class Application
{
public:
	static constexpr int WINDOW_WID = 800;				// ウィンドウの横サイズ
	static constexpr int WINDOW_HIG = 600;				// ウィンドウの縦サイズ
	//constexper ⇒ コンパイル時に値が確定されるので、実行が早くなる 
	bool SystemInit(void);	//初期化処理
	void Run(void);			//ゲーム起動
	bool Release(void);		//解放処理(最後の一回のみ実行)

private:
	SceneManager* sceneM;	//SceneManagerクラスのインスタンスのポインタ
                                // (クラスを破棄するまで使える)

	void Update(void);		//更新処理
	void Draw(void);		//描画処理
};

Applicationのコンストラクタに初期化処理を追加。
(Application.cpp)

//コンストラクタ
Application::Application(void) {
	sceneM = nullptr;
}

オブジェクト作成とSystemInit()を仕込む。
(Application.cpp)

//初期化処理(最初の一回のみ実行)
bool Application::SystemInit(void)
{
//-----------------
// システム設定
//-----------------
SetWindowText("2505889 ゆき);			// ウィンドウのタイトルの設定
SetGraphMode(WINDOW_WID, WINDOW_HIG, 32);		// ウィンドウのサイズと色モードの設定
ChangeWindowMode(true);							// ウィンドウの表示モード(true=ウィンドウモード/false=フルスクリーン)

int err = DxLib_Init();							// DXライブラリの初期化
if (err == -1)return false;

SRand((unsigned int)time(NULL));

//オブジェクトの作成
sceneM = new SceneManager();
if (sceneM == nullptr)return false;

if (sceneM->SystemInit() == false)return false;

}

Draw関数とdelete、ポインタの初期化を仕込む。
(SceneManager.cpp)

void Application::Draw(void)
{
	SetDrawScreen(DX_SCREEN_BACK);
	CrearDrawScreen();

	sceneM->Draw();

	ScreenFlip();
}

bool Application::Release(void)
{

	delete sceneM;
	sceneM = nullptr;

	if (DxLib_End() == -1)return true;

	return true;
}

main.cppをApplicationクラスを利用した形式に変更する。
DxLib以外のincludeを削除して、include”Application.h”を追加。
前段階として、WinMain()以外を削除して、WinMain()自体の中身もreturn 0;だけ残して全削除
(main.cpp)

//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:
//-----------------------------------------------------------------------------
#include <DxLib.h>
#include"Application.h"


//-----------------
// WinMain関数
//-----------------
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
	return 0;					// ゲームの正常終了
}

各関数の呼び出しを記述していく。
(main.cpp)

//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:
//-----------------------------------------------------------------------------
#include <DxLib.h>
#include"Application.h"


//-----------------
// WinMain関数
//-----------------
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
	//アプリケーションクラスのインスタンス(オブジェクト)の定義
	Application apl;	//ローカル変数だが、WinMain配下にあるため終了まで有効

	//初期化処理
	if(apl.SystemInit()==false)return -1;

	//ゲームの起動
	apl.Run();

	//解放処理
	if (apl.Release() == false)return -1;

	return 0;		// ゲームの正常終了
}

Application.cpp、Application.h、SceneManager.cpp、SceneManager.h以外をプロジェクトから除外。
各ファイルを右クリック⇒「プロジェクトから除外」

タイトル画面を処理するクラスの作成。
ソリューションエクスプローラーから
ソースファイル(右クリック)⇒追加⇒既存の項目⇒SceneTitle.cpp
ヘッダーファイル(右クリック)⇒追加⇒既存の項目⇒SceneTitle.h
それぞれを、TitleScene.cpp、TitleScene.hにリネーム。

クラス宣言を記載。
(TitleScene.h)

#pragma once

class TitleScene {

public:
	static constexpr int TITLE_WID = 800;	//タイトル画像の幅
	static constexpr int TITLE_HIG = 475;	//タイトル画像の高さ

	TitleScene(void);	//コンストラクタ
	~TitleScene(void);	//デストラクタ

	bool SystemInit(void);	//初期化処理(最初の一回のみ実行)
	void GameInit(void);	//ゲーム機動・再開時に必ず呼び出す関数
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool Release(void);		//解放処理(最後の一回のみ実行)

private:
	int titleImage;		//タイトル画像のハンドル番号

};

空の関数を作っていく。
その後、コンストラクタでtitleImageの初期化。
SystemInit()にTitleImageの読み込み、Update()内にSceneTitleUpdate()の中身をペースト。
(TitleScene.cpp)

include <DxLib.h>
#include <time.h>
#include"TitleScene.h"

//コンストラクタ
TitleScene::TitleScene(void)
{
	titleImage = -1;
}

//デストラクタ
TitleScene::~TitleScene(void)
{

}

//初期化処理(最初の一回のみ実行)
bool TitleScene::SystemInit(void)
{
	titleImage = LoadGraph("image/title.png");
	if (titleImage == -1)return false;

}

//ゲーム機動・再開時に必ず呼び出す関数
void TitleScene::GameInit(void)
{	

}

//更新処理
void TitleScene::Update(void)
{
	if (nowSpaceKey == 0 && prevSpaceKey == 1) {
		//アップトリガーでスペースキーの押下を判定
		//SceneGameSysInit();
		SceneGameInit();
		nowStageNum = 1;
		sceneKind = SCENE_KIND_GAME;
	}

}

削除済みの関数等を参照していてエラーが出るので、修正していく。
まずはnowSpaceKeyとprevSpaceKeyの宣言をクラス内に追加。
また、入力を受けるゲッター関数をインライン関数として記述。

#pragma once

#include "StDefine.h"

class SceneManager
{
public:
	SceneManager(void);		//コンストラクタ
	~SceneManager(void);	//デストラクタ

	bool SystemInit(void);	//初期化処理(最初の一回のみ実行)
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool Release(void);		//解放処理(最後の一回のみ実行)

	int NowSpaceKey(void) { return prevSpaceKey; }
	int GetPrevSpaceKey(void) { return prevSpaceKey; }

private:
	eSceneKind scene_ID;	//現在のシーンID番号

	int nowSpaseKey;		//スペースキーの現在のフレームでの状態を格納
	int prevSpaceKey;		//スペースキーの直前のフレームでの状態を格納
};

SystemInit()に初期化処理を追加。
(SceneManager.cpp)

bool SceneManager::SystemInit(void)
{
	scene_ID = SCENE_KIND_TITLE;
        prevSpaceKey = nowSpaceKey = 0;

	return true;
}

Update()にキー状態の更新を仕込む。
(SceneManager.cpp)

//初期化処理(最初の一回のみ実行)
void SceneManager::Update(void)
{
	//スペースキーの状態を更新
	prevSpaceKey = nowSpaceKey;	//現在のキー状態を直前の状態として保存
	nowSpaceKey = CheckHitKey(KEY_INPUT_SPACE);	//現在のキー状態を更新
}

これを動作させるために、TitleSeneクラスにインスタンスのポインタを準備する必要がある。

#pragma once

#include "StDefine.h"

class SceneManager
{
public:
	SceneManager(SceneManager* scenem);		//コンストラクタ
	~SceneManager(void);	//デストラクタ

	bool SystemInit(void);	//初期化処理(最初の一回のみ実行)
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool Release(void);		//解放処理(最後の一回のみ実行)

	int NowSpaceKey(void) { return prevSpaceKey; }
	int GetPrevSpaceKey(void) { return prevSpaceKey; }

private:
	eSceneKind scene_ID;	//現在のシーンID番号

	int nowSpaseKey;		//スペースキーの現在のフレームでの状態を格納
	int prevSpaceKey;		//スペースキーの直前のフレームでの状態を格納
};

クラス参照を追加
(TitleScene.h)

#pragma once

class SceneManager;

class TitleScene {

public:
	static constexpr int TITLE_WID = 800;	//タイトル画像の幅
	static constexpr int TITLE_HIG = 475;	//タイトル画像の高さ

	TitleScene(void);	//コンストラクタ
	~TitleScene(void);	//デストラクタ

	bool SystemInit(void);	//初期化処理(最初の一回のみ実行)
	void GameInit(void);	//ゲーム機動・再開時に必ず呼び出す関数
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool Release(void);		//解放処理(最後の一回のみ実行)

private:
	int titleImage;		//タイトル画像のハンドル番号

        SceneManager* sceneM  //シーンマネージャークラスのインスタンスのポインタ
};

コンストラクタ内で宣言。
(TitleScene.cpp)

//コンストラクタ
TitleScene::TitleScene(SceneManager* scenem)
{
	titleImage = -1;
	sceneM = scenem;
}

(TitleScene.cpp)

#pragma once

#include"StDefine.h"

class SceneManager;

class TitleScene {

public:
	static constexpr int TITLE_WID = 800;	//タイトル画像の幅
	static constexpr int TITLE_HIG = 475;	//タイトル画像の高さ

	TitleScene(void);	//コンストラクタ
	~TitleScene(void);	//デストラクタ

	bool SystemInit(void);	//初期化処理(最初の一回のみ実行)
	void GameInit(void);	//ゲーム機動・再開時に必ず呼び出す関数
	void Update(void);		//更新処理
	void Draw(void);		//描画処理
	bool Release(void);		//解放処理(最後の一回のみ実行)

private:
	int titleImage;		//タイトル画像のハンドル番号

	SceneManager* sceneM;	//シーンマネージャークラスのインスタンスのポインタ
	eSceneKing nextScene_ID;//次に遷移するシーンのID番号
};

コメント

タイトルとURLをコピーしました