引き続き爆発処理を実装していく。
(Explosion.cpp)
bool Explosion::Update(void)
{
if (enemyFlag == true) {
enemyCounter++;
if (enemyCounter >= ENEMY_EXPLOSION_TIME) EnemyExplosionEnd();
}
if(playerFlag == true) {
playerCounter++;
if (playerCounter >= PLAYER_EXPLOSION_TIME) PlayerExplosionEnd();
}
return true;
}
bool Explosion::Draw(void)
{
if (enemyFlag == true) {
DrawGraph(enemyPos.x, enemyPos.y, image, true);
}
if(playerFlag == true) {
if ((playerCounter / 4) % 2 == 0){
// 点滅処理
DrawGraph(playerPos.x, playerPos.y, image, true);
return true;
}
}
return true;
}
playerCounter / 4
→ カウンタを4で割って「4フレームごとに1増える値」に変換してる。
つまり「4フレームを1単位」として周期を作ってる。( ... ) % 2 == 0
→ その単位が偶数のとき(=ON)、奇数のとき(=OFF)で切り替える。
🧠 結果的な動作
- 4フレーム分は
true(表示) - 次の4フレーム分は
false(非表示) - これを繰り返す
つまり、**「8フレーム周期で点滅」**してます。
(4フレーム表示 → 4フレーム消える → また表示 → …)
💡 まとめ
内容 | 意味 |
|---|---|
/4 | 「4フレームごとに切り替える」スピード調整 |
%2 | 「ON/OFFの交互制御」 |
| 結果 | 8フレーム周期で1回点滅(4フレーム表示・4フレーム非表示) |
(by ChatGPT)
プレイヤー撃破時の爆発表示を実装。
(GameScene.cpp)
bool GameScene::CollisionCheckEnemyBullet(void)
{
if (pl->GetAlive() == false) return false;
{
for (int yy = Enemy::Enemy_DISP_YNUM -1; yy >= 0; yy--) {
for (int xx = 0; xx < Enemy::ENEMY_DISP_XNUM; xx++) {
if (eBullet->GetAlive(xx.yy) == true) {
//敵弾が存在している
POSITION ebPos = eBullet->GetPos(xx,yy);
if ((pl->GetPos().y + Player::PLAYER_HIG > ebPos.y) //プレイヤーの下端>敵弾の上端
&& (pl->GetPos().y < ebPos.y + EnemyBullet::ENEMY_BULLET_HIG) //プレイヤーの上端<敵弾の下端
&& (pl->GetPos().x < ebPos.x + EnemyBullet::ENEMY_BULLET_WID) //プレイヤーの左端<敵弾の右端
&& (pl->GetPos().x + Player::PLAYER_WID > ebPos.x)) //プレイヤーの右端>敵弾の左端
{
//プレイヤーに命中
eBullet->SetAliveOff(xx, yy);//敵弾を消滅させる
pl->SetAliveOff(); //プレイヤーを撃破状態にする
POSITION pos = pl->GetPos();
pos.x -= (Explosion::EXPLOSION_WID - Player::PLAYER_WID) / 2;
Application::WINDOW_HIG - Player::PLAYER_HIG;
expl->PlayerExplosionStart(pos);//爆発エフェクトの生成
return true;
}
}
}
}
}
return false;
}
※爆発の表示座標(プレイヤー撃破時)
pos.x -= (Explosion::EXPLOSION_WID - Player::PLAYER_WID) / 2;
pos.y = Application::WINDOW_HIG - Explosion::EXPLOSION_HIG;
これは:
- X座標 → 爆発画像がプレイヤーより横に大きいので、
「中心を合わせる」ために左へ半分ずらす。 - Y座標 → 爆発画像が縦に大きいので、
「下端がウィンドウの底ギリギリになるように」上に持ち上げている。
Player画像 は「機体の下端(足)」がウィンドウの底に接している。
→ pos.y = Application::WINDOW_HIG - Player::PLAYER_HIG;
Explosion画像 は「中心が膨らむ」タイプ。
→ 同じYで描くと、半分が下に隠れる。
→ 爆発の中心がプレイヤー機体の中央にくる=自然な見た目。
📊 つまり:
| 行動 | 意図 |
|---|---|
x を左にずらす | 横方向で画像の中心を合わせる |
y を上にずらす | 爆発の下端が画面に隠れないようにする(全体を見せる) |
👁️🗨️ 実際に表示される見た目
・“爆発の重心=機体の中心” という演出バランス。
・プレイヤーの位置を基準に爆発が「ちょっと上に」出る。
・そのため、爆発が機体を包み込むように見えて、自然。
(by ChatGPT)
Updateにプレイヤー撃破時の条件も追加する
(GameScene.cpp)
void GameScene::Update(void)
{
bool eExpFlg = expl->GetEnemyExplosionFlag(); //敵爆発中フラグ取得
bool pExpFlg = expl->GetPlayerExplosionFlag(); //自機爆発中フラグ取得
if(eExpFlg||pExpFlg) {
//爆発処理中は他の更新処理を行わない
expl->Update();
return;
}
StageExitConditionsCheck()関数内プレイヤーが撃破時の処理を、プレイヤーの爆発表示が終わるまで待つ様に変更(プレイヤーの存在フラグが偽の場合、爆発表示フラグが偽ならステージ終了条件を設定するという方式に変更する)
(GameScene.cpp)
eStageExitConditionsKind GameScene::StageExitConditionCheck(void)
{
eStageExitConditionsKind exitCondition = ESTAGE_EXIT_NON;
//敵の残機数を取得する
int enemyNum = en->GetEnemyRestNum();
if (enemyNum == 0) {
//敵の残機数が0なので、プレイヤーがステージをクリアした
exitCondition = ESTAGE_EXIT_CLEAR;
}
else if (pl->GetAlive() == false) {
//プレイヤーがやられた
if (expl->GetPlayerExplosionFlag() == false) {
//爆発処理が終了している場合のみ
exitCondition = ESTAGE_EXIT_ENEMY_SHOT;
}
}
else if (en->CheckHitEdgeProc() == ENEMY_HIT_EDGE_DOWN) {
//敵が最下段に到達した
exitCondition = ESTAGE_EXIT_ENEMY_OCCUPATION;
}
return exitCondition;
}
スコアを実装していく。まずは変数の準備から(privateで)。
(GameScene.h)
#pragma once
#include"StDefine.h"
class SceneManager;
class Player;
class PlayerBullet;
class Enemy;
class EnemyBullet;
class Explosion;
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のインスタンスのポインタ
Explosion* expl; //ExplosionClassのインスタンスのポインタ
int nowStageNo; //現在のステージ番号
int nowScore; //現在のスコア
int highScore; //ハイスコア
int scoreTbl[ENEMY_KIND_MAX]; //敵キャラの種類ごとのスコアテーブル
eStageExitConditionsKind StageExitConditionsCheck(void);
bool CollisionCheckPlayerBullet(void);//衝突判定
bool CollisionCheckEnemyBullet(void); //敵弾との衝突判定
eSceneKind nextScene_ID; //次に遷移するシーンのID番号
int nowBKeyPress;
int prevBKeyPress;
// テスト用のキーの状態
#ifdef _DEBUG
int nowWKeyPress; //デバッグ用(W)
int prevWKeyPress;
int nowLKeyPress; //デバッグ用(L)
int prevLKeyPress;
int nowOKeyPress; //デバッグ用(O)
int prevOKeyPress;
#endif //_DEBUG
};
スコアの初期化処理。
(GameScene.cpp)
void GameScene::GameInit(void)
{
pl->GameInit();
pBullet->GameInit();
en->GameInit();
eBullet->GameInit();
expl->GameInit();
nowStageNo = 0;
nextScene_ID = SCENE_KIND_GAME;
for(int ii = 0;ii<ENEMY_KIND_MAX;ii++){
scoreTbl[ii] = 10 + (5 * ii);
}
nowscore = 0;
highScore = 0;
nowBKeyPress = prevBKeyPress = 0;
// テスト用のキーの状態
#ifdef DEBUG
nowWKeyPress = prevWKeyPress = 0; //デバッグ用(W)
nowLKeyPress = prevLKeyPress = 0; //デバッグ用(L)
nowOKeyPress = prevOKeyPress = 0; //デバッグ用(O)
#endif // DEBUG
}
敵種別判別用のテーブル定義。
(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 eArray[y][x].flag; }
void SetAliveOff(int x, int y) { eArray[y][x].flag = false; }
POSITION GetPos(int x, int y) { return eArray[y][x].pos; }
void SetPos(int x, int y, POSITION pos) { eArray[y][x].pos = pos; }
eEnemyMoveDirection GetMoveDir(void) { return eMoveDirection; }
eEnemyMoveDirection GetNextMoveDir(void) { return eNextMoveDirection; }
void SetMoveDir(eEnemyMoveDirection dir) { eMoveDirection = dir; }
void SetNextMoveDir(eEnemyMoveDirection dir) {eNextMoveDirection = dir; }
int GetKind(int x, int y) { return eArray[y][x].kind; }
// 敵キャラ
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_CUT_INTERVAL = 2; //短縮する移動間隔
static constexpr int ENEMY_REST_PER_MINIMUM = 10; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_2 = 20; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_3 = 40; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_4 = 60; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_5 = 80; //敵キャラ残機数の最小割合(%)
private:
//敵キャラの表示関連
static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;
static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 32; //敵移動のインターバル
// 敵キャラ
int imageArray[ENEMY_KIND_MAX][ENEMY_PATTERNS]; // 敵の画像ハンドル番号
charData eArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM]; // 敵のX座標表示位置と生存フラグと種類のテーブル
bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM]; // 敵の存在フラグテーブル
eEnemyMoveDirection eMoveDirection; //敵キャラの現在の移動方向
eEnemyMoveDirection eNextMoveDirection; //敵キャラの下移動後の移動方向
int eMoveIntervalCounter; //敵キャラ移動の間隔調整用カウンタ
int eAnimCounter; //敵キャラのアニメーションカウンタ
};
スコア加算とハイスコア更新処理。
スコア更新用の関数をヘッダーに定義
(GameScene.h)
#pragma once
#include"StDefine.h"
class SceneManager;
class Player;
class PlayerBullet;
class Enemy;
class EnemyBullet;
class Explosion;
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のインスタンスのポインタ
Explosion* expl; //ExplosionClassのインスタンスのポインタ
int nowStageNo; //現在のステージ番号
int nowScore; //現在のスコア
int highScore; //ハイスコア
int scoreTbl[ENEMY_KIND_MAX]; //敵キャラの種類ごとのスコアテーブル
eStageExitConditionsKind StageExitConditionCheck(void);//ステージ終了条件の確認
bool CollisionCheckPlayerBullet(void); //衝突判定
bool CollisionCheckEnemyBullet(void); //敵弾との衝突判定
void AddScore(int add, int kind); //スコア加算処理
eSceneKind nextScene_ID; //次に遷移するシーンのID番号
int nowBKeyPress;
int prevBKeyPress;
// テスト用のキーの状態
#ifdef _DEBUG
int nowWKeyPress; //デバッグ用(W)
int prevWKeyPress;
int nowLKeyPress; //デバッグ用(L)
int prevLKeyPress;
int nowOKeyPress; //デバッグ用(O)
int prevOKeyPress;
#endif //_DEBUG
};
(GameScene.cpp)
bool GameScene::CollisionCheckPlayerBullet(void)
{
if (pBullet->GetAlive() == true) {
for (int yy = 0; yy < Enemy::ENEMY_DISP_YNUM; yy++) {
for (int xx = 0; xx < Enemy::ENEMY_DISP_XNUM; xx++) {
if (en->GetAlive(xx,yy) == false)continue;
POSITION epos = en->GetPos(xx, yy);
if (
(epos.y + Enemy::ENEMY_HIG > pBullet->GetPos().y && //判定1:敵の下端のY座標 > 弾の上端のY座標
(epos.y < pBullet->GetPos().y + Player::PLAYER_BULLET_HIG) && //判定2:敵の上端のY座標 < 弾の下端のY座標
(epos.x < pBullet->GetPos().x + Player::PLAYER_BULLET_WID) && //判定3:敵の左端のX座標 < 弾の右端のX座標
(epos.x + Enemy::ENEMY_WID > pBullet->GetPos().x //判定4: 敵の右端のX座標 > 弾の左端のX座標
)
{
// プレイヤー弾は消滅
pBullet->SetAliveOff();
// 敵キャラも消滅
en->SetAliveOff(xx,yy);
// 爆発エフェクトの生成
POSITION pos = en->GetPos(xx, yy);
pos.x -= (Explosion::EXPLOSION_WID - Enemy::ENEMY_WID) / 2;
expl->ExplosionStart(pos);
// スコア加算
AddScore(scoreTbl[en->GetKind(xx, yy)], en->GetKind(xx, yy));
return true;
}
}
}
}
return false;
}
Draw()内にスコア表示を追加。
(GameScene.cpp)
void GameScene::Draw(void)
{
// プレイヤーの描画
pl->Draw();
// プレイヤー弾の描画
pBullet->Draw();
// 敵の描画
en->Draw();
// 敵弾の描画
eBullet->Draw();
// 爆発エフェクトの描画
expl->Draw();
//文字列表示
DrawFormatString(10, 10, 0xffffff, "PlayerStock:%d", pl->GetPlayerStock());
DrawFormatString(10, 28, 0xffffff, "BombStock:%d", pBullet->GetBombStock());
DrawFormatString(10, 46, 0xffffff, "NowStage:%d", nowStageNo);
DrawFormatString(600, 10, 0xffffff, "NowScore:%d", nowscore);
DrawFormatString(600, 28, 0xffffff, "HighScore:%d", highScore);
ScreenFlip(); // 裏の画面を表の画面に瞬間コピー
}
UFOを出現させるためのスペース確保。まずは敵のY座標を3行分下げる。
(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 eArray[y][x].flag; }
void SetAliveOff(int x, int y) { eArray[y][x].flag = false; }
POSITION GetPos(int x, int y) { return eArray[y][x].pos; }
void SetPos(int x, int y, POSITION pos) { eArray[y][x].pos = pos; }
eEnemyMoveDirection GetMoveDir(void) { return eMoveDirection; }
eEnemyMoveDirection GetNextMoveDir(void) { return eNextMoveDirection; }
void SetMoveDir(eEnemyMoveDirection dir) { eMoveDirection = dir; }
void SetNextMoveDir(eEnemyMoveDirection dir) {eNextMoveDirection = dir; }
int GetKind(int x, int y) { return eArray[y][x].kind; }
// 敵キャラ
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_START_Y = (ENEMY_HIG + ENEMY_DISP_Y_INTERVAL) * 3;//敵キャラの表示開始Y座標
// 敵キャラの画面表示関連
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_CUT_INTERVAL = 2; //短縮する移動間隔
static constexpr int ENEMY_REST_PER_MINIMUM = 10; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_2 = 20; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_3 = 40; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_4 = 60; //敵キャラ残機数の最小割合(%)
static constexpr int ENEMY_REST_PER_MINI_5 = 80; //敵キャラ残機数の最小割合(%)
private:
//敵キャラの表示関連
static constexpr int ENEMY_DISP_ALL_NUM = ENEMY_DISP_XNUM * ENEMY_DISP_YNUM;
static constexpr int ENEMY_MOVE_INTERVAL_COUNT = 32; //敵移動のインターバル
// 敵キャラ
int imageArray[ENEMY_KIND_MAX][ENEMY_PATTERNS]; // 敵の画像ハンドル番号
charData eArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM]; // 敵のX座標表示位置と生存フラグと種類のテーブル
bool flgArray[ENEMY_DISP_YNUM][ENEMY_DISP_XNUM]; // 敵の存在フラグテーブル
eEnemyMoveDirection eMoveDirection; //敵キャラの現在の移動方向
eEnemyMoveDirection eNextMoveDirection; //敵キャラの下移動後の移動方向
int eMoveIntervalCounter; //敵キャラ移動の間隔調整用カウンタ
int eAnimCounter; //敵キャラのアニメーションカウンタ
};
敵の初期配置をずらす。
(Enemy.cpp)
#include<DxLib.h>
#include"Application.h"
#include"Player.h"
#include"Enemy.h"
//-----------------
// 変数の宣言
//-----------------
Enemy::Enemy()
: imageArray{} // 2次元配列を 0 クリア
, eArray{} // 構造体配列を 0 クリア
, flgArray{} // 0 クリア(全部 false)
, eMoveDirection(ENEMY_DIR_RIGHT)
, eNextMoveDirection(ENEMY_DIR_NON)
, eMoveIntervalCounter(-1)
, eAnimCounter(0)
{
}
Enemy::~Enemy()
{
}
bool Enemy::SystemInit(void)
{
const char* fileName[] = {
{"image/Enemy_1.png"},
{"image/Enemy_2.png"},
{"image/Enemy_3.png"},
};
//敵の画像の読込み
for (int ii = 0; ii < ENEMY_KIND_MAX; ii++) {
int err = LoadDivGraph(fileName[ii], ENEMY_PATTERNS, ENEMY_PATTERNS, 1, ENEMY_WID, ENEMY_HIG, imageArray[ii]);
if (err == -1)return false;
}
return true;
}
void Enemy::GameInit(void)
{
//-----------------
// 変数の初期化
//-----------------
// 敵キャラの変数テーブルの初期化
for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
eArray[yy][xx].pos.x = (ENEMY_WID + ENEMY_DISP_X_DISTANCE) * xx;
eArray[yy][xx].pos.y = ENEMY_DISP_START_Y + (ENEMY_HIG + ENEMY_DISP_Y_DISTANCE) * yy;
eArray[yy][xx].flag = true;
if (yy < 2)
{
eArray[yy][xx].kind = ENEMY_KIND_3;
}
if (yy < 4)
{
eArray[yy][xx].kind = ENEMY_KIND_2;
}
else
{
eArray[yy][xx].kind = ENEMY_KIND_1;
}
}
}
eMoveDirection = ENEMY_DIR_RIGHT;
eNextMoveDirection = ENEMY_DIR_NON;
eMoveIntervalCounter = -1; //カウンタ初期化(00:15~)
eAnimCounter = -1; //アニメーションカウンタ初期化
}
void Enemy::OccupationInit(void)
{
}
void Enemy::Update(void)
{
int rnum = GetEnemyRestNum();
int per = (rnum * 100) / ENEMY_DISP_ALL_NUM;
if (per > ENEMY_REST_PER_MINIMUM) {
eMoveIntervalCounter++;
if (eMoveIntervalCounter > 0) {
int cutCount = 0;
if (per < ENEMY_REST_PER_MINI_5) {
if (per < ENEMY_REST_PER_MINI_2) {
cutCount = 16;
}
else if (per < ENEMY_REST_PER_MINI_3) {
cutCount = 14;
}
else if (per < ENEMY_REST_PER_MINI_4) {
cutCount = 10;
}
else {
cutCount = 8;
}
}
if (eMoveIntervalCounter >= (ENEMY_MOVE_INTERVAL_COUNT-ENEMY_MOVE_CUT_INTERVAL*cutCount)) {
eMoveIntervalCounter = -1;
}
return;
}
}
eAnimCounter++;
if (eAnimCounter >= ENEMY_PATTERNS)eAnimCounter = 0;
for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
if (eArray[yy][xx].flag) {
switch (eMoveDirection) {
case ENEMY_DIR_RIGHT:
eArray[yy][xx].pos.x += ENEMY_MOVE_X_SPEED;
break;
case ENEMY_DIR_LEFT:
eArray[yy][xx].pos.x -= ENEMY_MOVE_X_SPEED;
break;
case ENEMY_DIR_DOWN:
eArray[yy][xx].pos.y += ENEMY_MOVE_Y_SPEED;
break;
}
}
}
}
// エリアの端にぶつかっていないかのチェック
eEnemyHitEdgeDir hitdir = CheckHitEdgeProc();
switch (hitdir) {
case ENEMY_HIT_EDGE_NON:
// 通常移動:次の方向に移る
if (eNextMoveDirection != ENEMY_DIR_NON) {
eMoveDirection = eNextMoveDirection;
eNextMoveDirection = ENEMY_DIR_NON;
}
break;
case ENEMY_HIT_EDGE_RIGHT:
eMoveDirection = ENEMY_DIR_DOWN;
eNextMoveDirection = ENEMY_DIR_LEFT;
break;
case ENEMY_HIT_EDGE_LEFT:
eMoveDirection = ENEMY_DIR_DOWN;
eNextMoveDirection = ENEMY_DIR_RIGHT;
break;
case ENEMY_HIT_EDGE_DOWN:
// 敵が最下段に到達 → 負け処理へ
break;
}
}
void Enemy::Draw(void)
{
// 敵の描画
for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
if (eArray[yy][xx].flag) {
DrawGraph(eArray[yy][xx].pos.x, eArray[yy][xx].pos.y, imageArray[eArray[yy][xx].kind][eAnimCounter], true);
}
}
}
}
bool Enemy::Release(void)
{
bool err = true;
for (int ii = 0; ii < ENEMY_KIND_MAX; ii++) {
for (int jj = 0; jj < ENEMY_PATTERNS; jj++) {
if (DeleteGraph(imageArray[ii][jj]) == -1)err = false;
}
}
return err;
}
//エリアの端にぶつかっていないかのチェック処理
eEnemyHitEdgeDir Enemy::CheckHitEdgeProc(void)
{
eEnemyHitEdgeDir hitdir = ENEMY_HIT_EDGE_NON;
int restnum;//その列に生き残っている敵の数を格納する変数(ローカル)
switch (eMoveDirection) {
//右方向に移動中なので、右端に接触していないかをチェックする
case ENEMY_DIR_RIGHT:
for (int xx = ENEMY_DISP_XNUM - 1; xx >= 0; xx--) {
restnum = 0;//敵が残っていなかった場合、チェックする列を移行するたびにチェックを初期化する
for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
if (eArray[yy][xx].flag == true) {
restnum++;
if (eArray[yy][xx].pos.x >= (Application::WINDOW_WID - ENEMY_WID)) {
hitdir = ENEMY_HIT_EDGE_RIGHT;
break;
}
}
}
if (hitdir != ENEMY_HIT_EDGE_NON || restnum > 0)break; //端に接触しているか、端に接触していなくても残っている敵がいる場合にbreak
}
break;
//左方向に移動中なので、左端に接触していないかをチェックする
case ENEMY_DIR_LEFT:
for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
restnum = 0;//敵が残っていなかった場合、チェックする列を移行するたびにチェックを初期化する
for (int yy = 0; yy < ENEMY_DISP_YNUM; yy++) {
if (eArray[yy][xx].flag == true) {
restnum++;
if (eArray[yy][xx].pos.x <= 0) {
hitdir = ENEMY_HIT_EDGE_LEFT;
break;
}
}
}
if (hitdir != ENEMY_HIT_EDGE_NON || restnum > 0)break; //端に接触しているか、端に接触していなくても残っている敵がいる場合にbreak
}
break;
//下方向に移動中なので、下端に接触していないかをチェックする
case ENEMY_DIR_DOWN:
for (int yy = ENEMY_DISP_YNUM - 1; yy > 0; yy--) {
restnum = 0;
for (int xx = 0; xx < ENEMY_DISP_XNUM; xx++) {
if (eArray[yy][xx].flag == true) {
restnum++;
if (eArray[yy][xx].pos.y >= (Application::WINDOW_HIG - ENEMY_HIG)) {
hitdir = ENEMY_HIT_EDGE_DOWN;
break;
}
}
}
if (hitdir != ENEMY_HIT_EDGE_NON || restnum > 0)break; //端に接触しているか、端に接触していなくても残っている敵がいる場合にbreak
}
break;
default:
break;
}
return hitdir;
}
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 (eArray[yy][xx].flag == true)num++;
}
}
return num;
}
UfoProcClassを追加。メンバを記載。
(UfoProc.h)
#pragma once
#include"StDefine.h"
class UfoProc
{
public:
static constexpr int UFO_WID = 48; //UFOの画像の横サイズ
static constexpr int UFO_HIG = 24; //UFOの画像の縦サイズ
static constexpr int UFO_DSP_SY = 28; //UFOの表示Y座標
static constexpr int UFO_SPEED = 4; //UFOの移動速度
static constexpr int UFO_EMERGE_INTERVAL = (60 * 30); //UFO出現間隔(60FPS×30秒)
static constexpr int UFO_RAND_TIME = (60 * 5); //UFO出現のランダム時間(60FPS×5秒)
static constexpr int UFO_EMARGE_CUT_TIME = (60 * 5); //UFO出現間隔短縮時間(60FPS×5秒)
UfoProc(void);
~UfoProc(void);
bool SystemInit(void);
void GameInit(void);
void Update(void);
void Draw(void);
bool Release(void);
private:
int image; //UFO画像ハンドル番号
charData ufoInfo; //UFO情報
int emergeIntervalCounter; //UFO出現間隔カウンタ
eEnemyHitEdgeDir emergeDir; //UFOの出現位置(左右)
//ENEMY_HIT_DIR_RIGHT:右から出現
//ENEMY_HIT_DIR_LEFT:左から出現
int emergeRandTime; //UFO出現のランダム時間
};
関数を実装してゆく。
(UfoProc.cpp)
//-----------------------------------------------------------------------------
// インベーダーゲーム
// 氏 名:ゆき
//-----------------------------------------------------------------------------
// UfoProcClass
#include <DxLib.h>
#include"Application.h"
#include "StDefine.h"
#include "UfoProc.h"
#include "Enemy.h"
UfoProc::UfoProc(void)
{
image = -1;
}
UfoProc::~UfoProc(void)
{
}
bool UfoProc::SystemInit(void)
{
image = LoadGraph("image/UFO.png");
if (image == -1)return false;
return true;
}
void UfoProc::GameInit(void)
{
ufoInfo.pos.x = 0;
ufoInfo.pos.y = UFO_DSP_SY;
ufoInfo.flag = false;
emergeIntervalCounter = 0;
emergeDir = ENEMY_HIT_EDGE_NON;
emergeRandTime = 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
続きは次回。

コメント