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;
}
}
}
まだ空の関数が残っているので、続きは次回。
コメント