2Dゲーム制作㉕(2025/10/08)

EnemyBullet.cppとEnemyBullet.hをプロジェクトに追加。

クラスを作成して中身を記載していく。
(EnemyBullet.h)

#pragma once

#include"Enemy.h"

class EnemyBullet
{
//-----------------------
// 定数定義
// -----------------------
	static constexpr int ENEMY_BULLET_MOVE = 3;	//敵弾の移動量
	static constexpr int ENEMY_BULLET_RAND_MAX = 99;
	static constexpr int ENEMY_BULLET_RAND_VALUE = 10;
public:
	static constexpr int ENEMY_BULLET_WID = 16;	//敵弾の画像幅
	static constexpr int ENEMY_BULLET_HIG = 25;	//敵弾の画像高さ

	EnemyBullet(Enemy* enemy);
	~EnemyBullet(void);

	bool SystemInit(void);
	bool GameInit(void);
	void UpdateShot(void);
	void UpdateMove(void);
	void Draw(void);
	bool Release(void);

private:
	Enemy* eInst;		//Enemyクラスのインスタンスのポインタ ※

	int img;
	POSITION posArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];
	bool flgArray[Enemy::ENEMY_DISP_YNUM][Enemy::ENEMY_DISP_XNUM];
};

     GameClass.Obj
  ↓           ↓
EnemyClass.Obj①   EnemyBulletClass.Obj
(pInst*)   ⇒     ↓
            EnemyClass.Obj②

GameClassオブジェクトから作成した①と
EnemyBulletClassオブジェクトから作成した②は同名の別オブジェクト。内容はリンクしない。
このため、*pInstという形で、EnemyClassのインスタンスした場合のポインタをEnemyBulletClassに記載しておくことで、EnemyBulletClassでEnemyClassオブジェクトを扱うことができる。

定数定義を一部private⇒publicにする。
(Enemy.h)

#pragma once
#include "Stdefine.h"

class Enemy
{

public:
	Enemy(void);
	~Enemy(void);

	bool SystemInit(void);
	void GameInit(void);
	void OccupationInit(void);
	void Update(void);
	void Draw(void);
	bool Release(void);

	eEnemyHitEdgeDir CheckHitEdgeProc(void);

	// 敵キャラ
	static constexpr int ENEMY_WID = 32;	// 敵の画像の横サイズ
	static constexpr int ENEMY_HIG = 23;	// 敵の画像の縦サイズ
	static constexpr int ENEMY_PATTERNS = 2;      //敵のアニメーション配列数
	static constexpr int ENEMY_DISP_X_DISTANCE = 8;	//敵キャラ同士の横の間隔
	static constexpr int ENEMY_DISP_Y_DISTANCE = 4;	//敵キャラ同士の縦の間隔

	// 敵キャラの画面表示関連
	static constexpr int ENEMY_DISP_XNUM = 8;				// 敵キャラの横の表示個数
	static constexpr int ENEMY_DISP_YNUM = 7;				// 敵キャラの縦の表示個数
	
	// 敵キャラの移動関連
	static constexpr int ENEMY_MOVE_X_SPEED = 4;			//敵の横方向の移動量
	static constexpr int ENEMY_MOVE_Y_SPEED = (ENEMY_HIG + ENEMY_DISP_Y_DISTANCE);//敵の縦方向移動量
	static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 8;	//敵移動のインターバル


private:
	//敵キャラの表示関連
	static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;

	// 敵キャラ
	int imageArray[ENEMY_PATTERNS];			// 敵の画像ハンドル番号
	POSITION posArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵のX座標表示位置テーブル
	bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵の存在フラグテーブル

	eEnemyMoveDirection eMoveDirection;		//敵キャラの現在の移動方向
	eEnemyMoveDirection eNextMoveDirection;	//敵キャラの下移動後の移動方向
	int eMoveIntervalCounter;		//敵キャラ移動の間隔調整用カウンタ

};

関数を作成していく。
(EnemyBullet.cpp)

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


EnemyBullet::EnemyBullet(Enemy* enemy)
{
    eInst = enemy;    //引数の Enemyクラスのインスタンスのポインタをポインタ変数に代入
}

EnemyBullet::~EnemyBullet(void)
{

}

bool EnemyBullet::SystemInit(void)
{
    img = LoadGraph("image/enemyBullet.png");
    if (enemyBulletImage == -1)return false;
    return true;
}

bool EnemyBullet::GameInit(void)
{
    for (int yy = 0; yy < Enemy::ENEMY_DISP_YNUM; yy++) {
        for (int xx = 0; xx < Enemy::ENEMY_DISP_XNUM; xx++) {
            posArray[yy][xx].x = posArray[yy][xx].y = 0;    //弾の位置初期化
            flgArray[yy][xx] = false;			//弾の存在フラグを初期化
        }
    }
    return true;

}

void EnemyBullet::UpdateShot(void)
{
    static int cooldown = 0;
    if (cooldown > 0) {         // クールダウン中は撃たない
        cooldown--;
        return;
    }

    // 次の発射までのフレーム数をランダム化(例:15〜45F)
    cooldown = 15 + GetRand(30); // ← SRand は Init で呼ばれてるのでOK

    // ---- 撃つ列をランダムに選ぶ ----
    // 何回かトライして、敵の残ってる列を引けたら撃つ
    for (int tries = 0; tries < Enemy::ENEMY_DISP_XNUM; ++tries) {
        int xx = GetRand(Enemy::ENEMY_DISP_XNUM - 1);  // 列をランダム選択

        // その列で一番下の生存敵を探す(下→上へ走査)
        int shooterY = -1;
        for (int yy = Enemy::ENEMY_DISP_YNUM - 1; yy >= 0; --yy) {
            if (flgArray[yy][xx]) {
                shooterY = yy;
                break;
            }
        }
        if (shooterY < 0) continue; // この列は全滅。別列を試す

        // ★列に弾が既に1発あるなら見送り(「1列1発」ルール)
        bool columnBusy = false;
        for (int yy = 0; yy < Enemy::ENEMY_DISP_YNUM; ++yy) {
            if (flgArray[yy][xx]) {
                columnBusy = true;
                break;
            }
        }
        if (columnBusy) continue;

        // 発射:敵の現在座標から出す(中央下端)
        flgArray[shooterY][xx] = true;
        posArray[shooterY][xx].x = posArray[shooterY][xx].x + (Enemy::ENEMY_WID - ENEMY_BULLET_WID) / 2;
        posArray[shooterY][xx].y = posArray[shooterY][xx].y + Enemy:: ENEMY_HIG;

        break; // 1フレームに1発だけ
    }
}

void EnemyBullet::UpdateMove(void)
{
    for (int xx = 0; xx < Enemy::ENEMY_DISP_XNUM; xx++) {
        for (int yy = Enemy::ENEMY_DISP_YNUM - 1; yy >= 0; yy--) {
            if (flgArray[yy][xx] == true) {
                //存在している敵弾のみ移動させる
                posArray[yy][xx].y += ENEMY_BULLET_MOVE;
                if (posArray[yy][xx].y > WINDOW_HIG) {
                    //弾が画面外に移動
                    flgArray[yy][xx] = false;
                }
            }
        }
    }

}

void EnemyBullet::Draw(void)
{
    for (int xx = 0; xx < Enemy::ENEMY_DISP_XNUM; xx++) {
        for (int yy = Enemy:: ENEMY_DISP_YNUM - 1; yy >= 0; yy--) {
            if (flgArray[yy][xx] == true) {
                //存在している敵弾のみ描画
                DrawGraph(posArray[yy][xx].x, posArray[yy][xx].y, img, true);
            }
        }
    }

}

bool EnemyBullet::Release(void)
{
    if (DeleteGraph(img) == -1)return false;
    return true;

}

Enemyクラスに、
敵キャラの存在フラグを取得するゲッター関数
敵キャラの座標を取得するゲッター関数 を作成。

#pragma once
#include "Stdefine.h"

class Enemy
{

public:
	Enemy(void);
	~Enemy(void);

	bool SystemInit(void);
	void GameInit(void);
	void OccupationInit(void);
	void Update(void);
	void Draw(void);
	bool Release(void);

	eEnemyHitEdgeDir CheckHitEdgeProc(void);

	bool GetAlive(xint x, int y); { return flgArray[y][x]; }
	POSITION GetPos(int x, int y) { return posArray[y][x]; }

	// 敵キャラ
	static constexpr int ENEMY_WID = 32;				// 敵の画像の横サイズ
	static constexpr int ENEMY_HIG = 23;				// 敵の画像の縦サイズ
	static constexpr int ENEMY_PATTERNS = 2;			//敵のアニメーション配列数
	static constexpr int ENEMY_DISP_X_DISTANCE = 8;	//敵キャラ同士の横の間隔
	static constexpr int ENEMY_DISP_Y_DISTANCE = 4;	//敵キャラ同士の縦の間隔

	// 敵キャラの画面表示関連
	static constexpr int ENEMY_DISP_XNUM = 8;				// 敵キャラの横の表示個数
	static constexpr int ENEMY_DISP_YNUM = 7;				// 敵キャラの縦の表示個数
	
	// 敵キャラの移動関連
	static constexpr int ENEMY_MOVE_X_SPEED = 4;			//敵の横方向の移動量
	static constexpr int ENEMY_MOVE_Y_SPEED = (ENEMY_HIG + ENEMY_DISP_Y_DISTANCE);//敵の縦方向移動量
	static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 8;	//敵移動のインターバル


private:
	//敵キャラの表示関連
	static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;

	// 敵キャラ
	int imageArray[ENEMY_PATTERNS];			// 敵の画像ハンドル番号
	POSITION posArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];//敵のX座標表示位置テーブル
	bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵の存在フラグテーブル

	eEnemyMoveDirection eMoveDirection;		//敵キャラの現在の移動方向
	eEnemyMoveDirection eNextMoveDirection;	//敵キャラの下移動後の移動方向
	int eMoveIntervalCounter;				//敵キャラ移動の間隔調整用カウンタ

};

GameSceneClassに、それぞれのインスタンスのポインタを準備。
(GameScene.h)

#pragma once

#include"StDefine.h"

class SceneManager;
class Player;
class PlayerBullet;
class Enemy;
class EnemyBullet;

class GameScene
{
public:
	static constexpr int STAGE_NUM_MAX = 5;	//最大ステージ数

	GameScene(SceneManager* scenem);
	~GameScene(void);

	bool SystemInit(void);		//ゲーム起動時の初期化処理
	void GameInit(void);		//ゲームシーンの初期化処理
	void SceneGameNextStageInit(void);//ステージクリア時の初期化処理
	void Update(void);			//ゲームシーンの更新処理
	void Draw(void);			//ゲームシーンの描画処理
	bool Release(void);			//ゲームシーンの解放処理

	void ExitConditionProc(void);


private:
	SceneManager* sceneM;	//SceneManagerClassのインスタンスのポインタ
	Player* pl;		//PlayerClassのインスタンスのポインタ
	PlayerBullet* pBullet;	//PlayerBulletClassのインスタンスのポインタ
	Enemy* en;		//EnemyClassのインスタンスのポインタ
	EnemyBullet* eBullet;	//EnemyBulletのインスタンスのポインタ

	eStageExitConditionsKind StageExitConditionsCheck(void);
	
	bool CollisionCheckPlayerBullet(void);//衝突判定
	bool CollisionCheckEnemyBullet(void); //敵弾との衝突判定

};

GameSdene.cppを修正していく。まずはincludeから。
(GameScene.cpp)

#include <DxLib.h>
#include "GameScene.h"
#include "Player.h"
#include "PlayerBullet.h"
#include "Enemy.h"
#include "EnemyBullet.h"
#include "Application.h"

メンバ関数を実装。
コンストラクタでポインタの初期化。各関数でオブジェクトの作成を実装。
(GameScene.cpp)


//コンストラクタ
GameScene::GameScene(SceneManager* scenem)
{
	sceneM = scenem;
	pl = nullptr;
	pBullet = nullptr;
	en = nullptr;
	eBullet = nullptr;
}

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

}

bool GameScene::SystemInit(void)
{
	pl = new Player();
	if (pl == nullptr)return false;

	pBullet = new PlayerBullet(sceneM,pl);
	if (pBullet == nullptr)return false;

	en = Enemy();
	if (en == nullptr)return false;

	eBullet = new EnemyBullet(en);
	if (eBullet == nullptr)return false;

	if (pl->SystemInit() == false)return false;
	if (pBullet->SystemInit() == false)return false;
	if (en->SystemInit() == false)return false;
	if (eBullet->SystemInit() == false)return false;

	return true;
}

(GameScene.cpp)

void GameScene::GameInit(void)
{
	pl->GameInit();
	pBullet->GameInit();
	en->GameInit();
	eBullet->GameInit();

	nowStageNo = 0;

}

//プレイヤーが勝利した時の再初期化処理
void GameScene::SceneGameNextStageInit(void)
{
	//敵キャラ関連の初期化
	en->GameInit();
	//プレイヤー関連の初期化
	//プレイヤーY座標は常に最下段なので再設定は不要
	//プレイヤー勝利時に呼ばれるので存在フラグの再設定は不要
	pl->SetDefaulotPos();
}

EnemyClassに関数を追加
(Enemy.h)

#pragma once
#include "Stdefine.h"

class Enemy;
{

public:
	Enemy(void);
	~Enemy(void);

	bool SystemInit(void);
	void GameInit(void);
	void OccupationInit(void);
	void Update(void);
	void Draw(void);
	bool Release(void);

	eEnemyHitEdgeDir CheckHitEdgeProc(void);
	int GetEnemyRestNum(void);				//敵の残機数を取得

	bool GetAlive(int x, int y){ return flgArray[y][x]; }
	POSITION GetPos(int x, int y) { return posArray[y][x]; }

	// 敵キャラ
	static constexpr int ENEMY_WID = 32;		// 敵の画像の横サイズ
	static constexpr int ENEMY_HIG = 23;		// 敵の画像の縦サイズ
	static constexpr int ENEMY_PATTERNS = 2;	//敵のアニメーション配列数
	static constexpr int ENEMY_DISP_X_DISTANCE = 8;	//敵キャラ同士の横の間隔
	static constexpr int ENEMY_DISP_Y_DISTANCE = 4;	//敵キャラ同士の縦の間隔

	// 敵キャラの画面表示関連
	static constexpr int ENEMY_DISP_XNUM = 8;	// 敵キャラの横の表示個数
	static constexpr int ENEMY_DISP_YNUM = 7;       // 敵キャラの縦の表示個数
	
	// 敵キャラの移動関連
	static constexpr int ENEMY_MOVE_X_SPEED = 4;		//敵の横方向の移動量
	static constexpr int ENEMY_MOVE_Y_SPEED = (ENEMY_HIG + ENEMY_DISP_Y_DISTANCE);//敵の縦方向移動量
	static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 8;	//敵移動のインターバル


private:
	//敵キャラの表示関連
	static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;

	// 敵キャラ
	int imageArray[ENEMY_PATTERNS];			// 敵の画像ハンドル番号
	POSITION posArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵のX座標表示位置テーブル
	bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵の存在フラグテーブル

	eEnemyMoveDirection eMoveDirection;	//敵キャラの現在の移動方向
	eEnemyMoveDirection eNextMoveDirection;	//敵キャラの下移動後の移動方向
	int eMoveIntervalCounter;		//敵キャラ移動の間隔調整用カウンタ

};

(Enemy.cpp)

int Enemy::GetEnemyRestNum(void)
{
	int num = 0;

	for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
		for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
			if (flgArray[yy][xx] == true)num++
		}
	}
	return num;
}

ゲッター関数と変数を追加。
(GameScene.h)

#pragma once

#include"StDefine.h"

class SceneManager;
class Player;
class PlayerBullet;
class Enemy;
class EnemyBullet;

class GameScene
{
public:
	static constexpr int STAGE_NUM_MAX = 5;	//最大ステージ数

	GameScene(SceneManager* scenem);
	~GameScene(void);

	bool SystemInit(void);		//ゲーム起動時の初期化処理
	void GameInit(void);		//ゲームシーンの初期化処理
	void SceneGameNextStageInit(void);//ステージクリア時の初期化処理
	void Update(void);			//ゲームシーンの更新処理
	void Draw(void);			//ゲームシーンの描画処理
	bool Release(void);			//ゲームシーンの解放処理

	void ExitConditionProc(void);

	eSceneKind getNextSceneID(void) { return nextScene_ID; }

private:
	SceneManager* sceneM;	//SceneManagerClassのインスタンスのポインタ
	Player* pl;		//PlayerClassのインスタンスのポインタ
	PlayerBullet* pBullet;	//PlayerBulletClassのインスタンスのポインタ
	Enemy* en;		//EnemyClassのインスタンスのポインタ
	EnemyBullet* eBullet;	//EnemyBulletのインスタンスのポインタ

	int nowStageNo;				//現在のステージ番号

	eStageExitConditionsKind StageExitConditionsCheck(void);
	
	bool CollisionCheckPlayerBullet(void);//衝突判定
	bool CollisionCheckEnemyBullet(void); //敵弾との衝突判定

	eSceneKind nextScene_ID;	//次に遷移するシーンのID番号
};

(Player.h)

#pragma once

#include "StDefine.h"

class Player
{
public:
	// プレイヤー
	const constexpr int PLAYER_WID = 32;		// プレイヤー画像の横サイズ
	const constexpr int PLAYER_HIG = 19;		// プレイヤー画像の縦サイズ
	const constexpr int PLAYER_MOVE_SPEED = 6;	// プレイヤーの左右の移動速度
	const constexpr int PLAYER_PLANE_MAX = 3;	// プレイヤーの最大保有機数

	Player(void);
	~Player(void);

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

	POSITION GetPos(void) { return pos; }
	bool GetAlive(void) { return aliveFlg; }
	void SetAlive(void) { aliveFlg = false; }
	int GetPlayerStock(void) { return playerStock; }
	void playerStockDec(void) { playerStock--; }
	void SetDefaultPos(void);

private:
	int img;		//プレイヤー画像のハンドル番号を格納する変数
	POSITION pos;		//プレイヤーの座標
	bool aliveFlg;		//プレイヤーの存在フラグ(true:生存、false:撃破)
	int playerStock;	//プレイヤーの残機
};

(Enemy.h)

#pragma once
#include "Stdefine.h"

class Enemy;
{

public:
	Enemy(void);
	~Enemy(void);

	bool SystemInit(void);
	void GameInit(void);
	void OccupationInit(void);
	void Update(void);
	void Draw(void);
	bool Release(void);

	eEnemyHitEdgeDir CheckHitEdgeProc(void);
	int GetEnemyRestNum(void);				//敵の残機数を取得

	bool GetAlive(int x, int y){ return flgArray[y][x]; }
	POSITION GetPos(int x, int y) { return posArray[y][x]; }
	void SetPos(int x, int y, POSITION pos) { posArray[y][x] = pos; }
	eEnemyMoveDirection GetMoveDir(void) { return eMoveDirection; }
	eEnemyMoveDirection GetNextMoveDir(void) { return eNextMoveDirection; }
	void SetMoveDir(eEnemyMoveDirection dir) { eMoveDirection = dir; }
	void SetNextMoveDir(eEnemyMoveDirection dir) {eNextMoveDirection = dir;	}


	// 敵キャラ
	static constexpr int ENEMY_WID = 32;		// 敵の画像の横サイズ
	static constexpr int ENEMY_HIG = 23;		// 敵の画像の縦サイズ
	static constexpr int ENEMY_PATTERNS = 2;	//敵のアニメーション配列数
	static constexpr int ENEMY_DISP_X_DISTANCE = 8;	//敵キャラ同士の横の間隔
	static constexpr int ENEMY_DISP_Y_DISTANCE = 4;	//敵キャラ同士の縦の間隔

	// 敵キャラの画面表示関連
	static constexpr int ENEMY_DISP_XNUM = 8;				// 敵キャラの横の表示個数
	static constexpr int ENEMY_DISP_YNUM = 7;				// 敵キャラの縦の表示個数
	
	// 敵キャラの移動関連
	static constexpr int ENEMY_MOVE_X_SPEED = 4;		//敵の横方向の移動量
	static constexpr int ENEMY_MOVE_Y_SPEED = (ENEMY_HIG + ENEMY_DISP_Y_DISTANCE);//敵の縦方向移動量
	static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 8;	//敵移動のインターバル



private:
	//敵キャラの表示関連
	static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;

	// 敵キャラ
	int imageArray[ENEMY_PATTERNS];			// 敵の画像ハンドル番号
	POSITION posArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM];// 敵のX座標表示位置テーブル
	bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM]	// 敵の存在フラグテーブル

	eEnemyMoveDirection eMoveDirection;	//敵キャラの現在の移動方向
	eEnemyMoveDirection eNextMoveDirection;	//敵キャラの下移動後の移動方向
	int eMoveIntervalCounter;		//敵キャラ移動の間隔調整用カウンタ

};

(GameScene.cpp)

void GameScene::ExitConditionProc(void)
{
	//ステージが終了したか
	eStageExitConditionsKind exit = StageExitConditionsCheck();
	if (exit != ESTAGE_EXIT_NON) {
		switch (exit) {
		case ESTAGE_EXIT_CLEAR:
			//条件1:プレイヤー勝利
			//ステージ番号を1加算
			nowStageNo++;
			//ステージ番号が最大ステージ数を超えたらゲーム終了
			if (nowStageNo > STAGE_NUM_MAX)
			{
				nextScene_ID = SCENE_KIND_GAMEOVER;
			}
			else {
				//次のステージに進む際に敵の位置やフラグを再初期化
				SceneGameNextStageInit();
			}
			break;

		case ESTAGE_EXIT_ENEMY_SHOT:
			//条件2:プレイヤーが敵弾にやられた
			pl->playerStockDec();
			if (pl->GetPlayerStock < 0) {
				//保有機数がなくなったらゲームオーバー
				nextScene_ID = SCENE_KIND_GAMEOVER;
			}
			else {
				//保有機数が残っていた場合に続行
				//プレイヤーのみ初期化
				pl->SetDefaultPos();
				pl->SetAlive();
			}

			break;
		case ESTAGE_EXIT_ENEMY_OCCUPATION:
			SceneGameNextStageInit();//配置初期化
			sceneKind = SCENE_KIND_GAMEOVER;
			break;
		}
	}


}

まだ空の関数が残っているので、続きは次回。

コメント

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