夏休み勉強会 6日目

最終日です。


敵の行動パターンを組む

それではまず。敵の行動パターンを組んでいこう。
まずはEnemy.hに必要なものを追加していく。
Enemy.hが以下のようになるようにコードを書き換えてくれ。

#pragma once

//	インクルード達
#include "Libraries/Development/Model3D.h"
#include "Libraries/Development/BoxCollider.h"

#include "../EnemyBullet/EnemyBullet.h"

//	前方宣言
class CommonResources;
class Player;

/// <summary>
/// 敵
/// </summary>
class Enemy
{
public:

	enum class StateID
	{
		Move,
		Shot,
		Tackle
	};

public:

	//	モデルのディレクトリパスと名前
	static constexpr wchar_t MODEL_DIRECTORY[]	= L"Resources/Models/";
	static constexpr wchar_t MODEL_NAME[]		= L"Enemy";

	//	衝突判定の大きさ
	static constexpr DirectX::SimpleMath::Vector3 COLLIDER_SIZE{ 2.0f, 2.0f, 2.0f };

	//	衝突判定位置のオフセット
	static constexpr DirectX::SimpleMath::Vector3 COLLIDER_OFFSET{ 0, 1.0f, 0 };

	//	開始座標
	static constexpr DirectX::SimpleMath::Vector3 START_POSITION{ 0.0f, 0.0f, 0.0f };
	
	//	開始回転
	static constexpr DirectX::SimpleMath::Vector3 START_ROTATION{ 0.0f, DirectX::XM_PI, 0.0f };

	//	旋回速度
	static constexpr float TURN_SPEED = 7.5f;

	//	移動速度
	static constexpr float MOVE_SPEED = 0.5f;

	//	銃口オフセット
	static constexpr DirectX::SimpleMath::Vector3 MUZZLE_OFFSET{ 0.0f, 0.25f, 0.0f };

	//	最大体力
	static constexpr int MAX_HP = 50;

	//	突撃速度
	static constexpr float TACKLE_SPEED = 10.0f;

	//	射撃数
	static constexpr int SHOT_NUM = 8;

	//	移動状態時間
	static constexpr float STATE_MOVE_TIME = 3.5f;

	//	突撃状態前隙
	static constexpr float STATE_TACKLE_BEFORE_TIME = 2.0f;
	//	突撃状態攻撃時間
	static constexpr float STATE_TACKLE_ATACK_TIME = 0.75f;
	//	突撃状態後隙
	static constexpr float STATE_TACKLE_AFTER_TIME = 1.0f;

	//	ダメージ効果時間
	static constexpr float DAMAGE_EFFECT_TIMER = 0.1f;

public:

	//	座標を取得
	const DirectX::SimpleMath::Vector3& GetPosition() const { return m_position; }

	//	衝突判定の取得
	const Develop::BoxCollider& GetCollider() const { return m_collider; }
	
	//	アクティブフラグの取得
	bool GetIsActive() const { return m_isActive; }

public:

	//	座標を設定
	void SetPosition(const DirectX::SimpleMath::Vector3& position);

	//	プレイヤーのポインタを設定
	void SetPlayer(Player* pPlayer) { m_pPlayer = pPlayer; }

public:

	//	コンストラクタ
	Enemy();
	//	デストラクタ
	~Enemy() = default;

	//	開始関数
	void Initialize(CommonResources* common);
	//	更新関数
	void Update(float deltaTime);
	//	描画関数
	void Render(const Develop::CameraObject& camera);
	//	終了関数
	void Finalize();

	//	ダメージ関数
	void Damage();

private:

	//	移動状態
	void StateMove(float deltaTime);
	//	射撃状態
	void StateShot(float deltaTime);
	//	突進状態
	void StateTackle(float deltaTime);

	//	移動関数
	void Move(const DirectX::SimpleMath::Vector3& moveVelocity, float deltaTime);
	//	射撃関数
	void Shot(const DirectX::SimpleMath::Vector3& direction);

	//	乱数生成
	int Random(int min, int max);
	
private:

	//	共通リソース
	CommonResources* m_commonResources;

	//	モデル
	Develop::Model3D m_model;

	//	衝突判定
	Develop::BoxCollider m_collider;

	//	座標
	DirectX::SimpleMath::Vector3 m_position;
	
	//	方向
	DirectX::SimpleMath::Vector3 m_direction;

	//	アクティブフラグ
	bool m_isActive;

	//	弾の配列
	std::vector<EnemyBullet> m_bullets;

	//	プレイヤーのポインタ
	Player* m_pPlayer;

	//	状態ID
	StateID m_stateID;

	//	体力
	int m_hp;

	//	状態時間
	float m_stateTimer;

	//	ダメージ効果時間
	float m_damageEffectTimer;

};

それができたら続いてEnemy.cppを書いていこう以下のコードになるように書き換えてくれ。

#include "pch.h"
#include "Enemy.h"

#include <random>
#include "../CommonResources.h"
#include "../Player/Player.h"

//	名前空間の使用
using namespace DirectX;

/// <summary>
/// コンストラクタ
/// </summary>
Enemy::Enemy()
	:
	m_commonResources(nullptr),
	m_isActive(true)
{
}

/// <summary>
/// 開始関数
/// </summary>
/// <param name="common">共通リソース</param>
void Enemy::Initialize(CommonResources* common)
{
	//	共通リソースの取得
	m_commonResources = common;

	//	コンテキストの取得
	ID3D11DeviceContext* context = common->GetDeviceResources()->GetD3DDeviceContext();
	//	共通ステートの取得
	CommonStates* states = common->GetCommonStates();

	//	リソース管理クラスの取得
	Develop::ResourceManager* resourceManager = common->GetResourceManager();

	//	モデルハンドルを取得
	Develop::ResourceManager::ModelHandle modelHandle;
	modelHandle = resourceManager->LoadModelCMO(MODEL_DIRECTORY, MODEL_NAME);

	//	モデルの初期化
	m_model.Initialize(context, states, modelHandle);

	//	衝突判定のサイズを設定
	m_collider.SetSize(COLLIDER_SIZE);

	//	開始座標を設定
	SetPosition(START_POSITION);

	//	モデルの回転を設定
	SimpleMath::Quaternion rotation;
	rotation = SimpleMath::Quaternion::CreateFromYawPitchRoll(START_ROTATION);
	m_model.SetRotate(rotation);

	//	方向の初期化
	m_direction = SimpleMath::Vector3::Forward;
	m_direction = SimpleMath::Vector3::Transform(m_direction, rotation);

	//	アクティブフラグをオンに
	m_isActive = true;

	//	配列の初期化
	m_bullets.clear();

	//	状態の初期化
	m_stateID = StateID::Move;

	//	体力の初期化
	m_hp = MAX_HP;

	//	状態時間の初期化
	m_stateTimer = 0.0f;

	//	ダメージ効果時間の初期化
	m_damageEffectTimer = 0.0f;
}

/// <summary>
/// 更新関数
/// </summary>
/// <param name="deltaTime">フレーム間秒数</param>
void Enemy::Update(float deltaTime)
{
	//	アクティブ状態かどうか
	if (m_isActive == false) { return; }

	//	状態ごとの更新をかける
	switch (m_stateID)
	{
	case Enemy::StateID::Move:	StateMove(deltaTime);	break;
	case Enemy::StateID::Shot:	StateShot(deltaTime);	break;
	case Enemy::StateID::Tackle:StateTackle(deltaTime);	break;
	default:											break;
	}

	//	ダメージ効果時間の更新
	m_damageEffectTimer -= deltaTime;
	m_damageEffectTimer = std::max(m_damageEffectTimer, 0.0f);

	//	弾の更新
	for (int i = 0; i < m_bullets.size(); i++)
	{
		m_bullets[i].Update(deltaTime);
	}
}

/// <summary>
///	描画関数
/// </summary>
/// <param name="camera">カメラ</param>
void Enemy::Render(const Develop::CameraObject& camera)
{
	//	アクティブ状態かどうか
	if (m_isActive == false) { return; }

	//	モデルの描画
	m_model.Render(camera);

	//	弾の描画
	for (int i = 0; i < m_bullets.size(); i++)
	{
		m_bullets[i].Render(camera);
	}
}

/// <summary>
/// 終了関数
/// </summary>
void Enemy::Finalize()
{
	//	弾の終了
	for (int i = 0; i < m_bullets.size(); i++)
	{
		m_bullets[i].Finalize();
	}
}

/// <summary>
/// ダメージ関数
/// </summary>
void Enemy::Damage()
{
	//	ダメージを受ける
	m_hp--;

	//	ダメージ効果時間を与える
	m_damageEffectTimer = DAMAGE_EFFECT_TIMER;

	//	ダメージが0以下になったら死ぬ
	if (m_hp < 0)
	{
		m_isActive = false;
	}
}

/// <summary>
/// 移動状態
/// </summary>
/// <param name="deltaTime">フレーム間秒数</param>
void Enemy::StateMove(float deltaTime)
{
	//	プレイヤー座標を取得
	SimpleMath::Vector3 playerPosition = m_pPlayer->GetPosition();

	//	プレイヤーへの方向ベクトルを求める
	SimpleMath::Vector3 toPlayerDireciton = playerPosition - m_position;
	toPlayerDireciton.Normalize();

	//	歩行速度をかけ合わせて移動させる
	Move(toPlayerDireciton * MOVE_SPEED, deltaTime);

	//	状態時間を更新
	m_stateTimer += deltaTime;
	if (m_stateTimer > STATE_MOVE_TIME)
	{
		//	乱数をもとに次の状態を決める
		int randNum = Random(0, 2);
		if (randNum == 0) { m_stateID = StateID::Shot; }
		else { m_stateID = StateID::Tackle; }

		//	状態時間を初期化
		m_stateTimer = 0.0f;
	}
}

/// <summary>
/// 射撃状態
/// </summary>
/// <param name="deltaTime">フレーム間秒数</param>
void Enemy::StateShot(float deltaTime)
{
}

/// <summary>
/// 突進状態
/// </summary>
/// <param name="deltaTime">フレーム間秒数</param>
void Enemy::StateTackle(float deltaTime)
{
}

/// <summary>
/// 移動関数
/// </summary>
/// <param name="moveVelocity">移動ベクトル</param>
/// <param name="deltaTime">フレーム間秒数</param>
void Enemy::Move(const DirectX::SimpleMath::Vector3& moveVelocity, float deltaTime)
{
	//	移動方向を計算
	SimpleMath::Vector3 moveDirection = moveVelocity;
	moveDirection.Normalize();

	//	今向いてる方向と移動方向で軸を算出
	SimpleMath::Vector3 moveAxis = m_direction.Cross(moveDirection);
	if (moveAxis.y > 0.0f) { moveAxis = SimpleMath::Vector3::Up; }
	else { moveAxis = SimpleMath::Vector3::Down; }

	//	今向いてる方向と移動方向の角度を算出
	float moveAngle = m_direction.Dot(moveDirection);
	moveAngle = std::min(1.0f, std::max(-1.0f, moveAngle));
	moveAngle = acosf(moveAngle);

	//	旋回速度と残りの角度を比較してより小さい方を取得
	moveAngle = std::min(moveAngle, TURN_SPEED * deltaTime);

	//	モデルをそれだけ回転させる
	SimpleMath::Quaternion rotate = m_model.GetRotate();
	rotate *= SimpleMath::Quaternion::CreateFromAxisAngle(moveAxis, moveAngle);
	m_model.SetRotate(rotate);

	//	前方ベクトルを更新
	m_direction = SimpleMath::Vector3::Transform(SimpleMath::Vector3::Forward, rotate);
	m_direction.Normalize();

	//	移動させる
	SetPosition(m_position + moveVelocity * deltaTime);

}

/// <summary>
/// 射撃関数
/// </summary>
/// <param name="direction">方向</param>
void Enemy::Shot(const DirectX::SimpleMath::Vector3& direction)
{
	//	起動する弾のポインタ
	EnemyBullet* bootBullet = nullptr;

	//	使えそうな弾を検索
	for (int i = 0; i < m_bullets.size(); i++)
	{
		//	使っていない弾を発見
		if (m_bullets[i].GetIsActive() == false)
		{
			bootBullet = &m_bullets[i];

			//	ループを抜ける
			break;
		}
	}

	//	使っていない弾がなければ作成
	if (bootBullet == nullptr)
	{
		//	新しく弾を生成する
		m_bullets.push_back(EnemyBullet());

		//	一番後ろの要素を取り出す
		bootBullet = &m_bullets.back();

		//	新しい弾の初期化処理
		bootBullet->Initialize(m_commonResources);
	}

	//	銃口座標
	SimpleMath::Vector3 muzzlePosition = MUZZLE_OFFSET;
	muzzlePosition = SimpleMath::Vector3::Transform(muzzlePosition, m_model.GetRotate());
	muzzlePosition += m_position;

	//	弾を発射
	bootBullet->Boot(muzzlePosition, direction);

}

/// <summary>
/// 乱数生成関数
/// </summary>
/// <param name="min">最小値</param>
/// <param name="max">最大値</param>
/// <returns>乱数</returns>
int Enemy::Random(int min, int max)
{
	//ランダムなシード値を使って乱数生成器を初期化
	static std::random_device seed;
	static std::mt19937 engine(seed());

	//	乱数を範囲内で生成
	return engine() % (max - min) + min;
}

/// <summary>
/// 座標を設定
/// </summary>
/// <param name="position">座標</param>
void Enemy::SetPosition(const DirectX::SimpleMath::Vector3& position)
{
	m_position = position;

	//	モデルの座標も設定
	m_model.SetPosition(position);
	//	衝突判定の座標も設定
	m_collider.SetPosition(position + COLLIDER_OFFSET);
}

これで行動を作っていく枠組みができた。今回はenumの状態IDを用いたswitch文での行動パターンを組んでいこうと思う。

突進行動を作成する

それではまず突進行動を作っていく。StateTackle関数に以下のコードを記述してくれ。

	//	状態時間を更新
	m_stateTimer += deltaTime;

	//	プレイヤーをサーチ
	if (m_stateTimer < STATE_TACKLE_BEFORE_TIME)
	{
		//	プレイヤー座標を取得
		SimpleMath::Vector3 playerPosition = m_pPlayer->GetPosition();

		//	プレイヤーへの方向ベクトルを求める
		SimpleMath::Vector3 toPlayerDireciton = playerPosition - m_position;
		toPlayerDireciton.Normalize();

		//	今向いてる方向と移動方向で軸を算出
		SimpleMath::Vector3 moveAxis = m_direction.Cross(toPlayerDireciton);
		if (moveAxis.y > 0.0f) { moveAxis = SimpleMath::Vector3::Up; }
		else { moveAxis = SimpleMath::Vector3::Down; }

		//	今向いてる方向と移動方向の角度を算出
		float moveAngle = m_direction.Dot(toPlayerDireciton);
		moveAngle = std::min(1.0f, std::max(-1.0f, moveAngle));
		moveAngle = acosf(moveAngle);

		//	旋回速度と残りの角度を比較してより小さい方を取得
		moveAngle = std::min(moveAngle, TURN_SPEED * deltaTime);

		//	モデルをそれだけ回転させる
		SimpleMath::Quaternion rotate = m_model.GetRotate();
		rotate *= SimpleMath::Quaternion::CreateFromAxisAngle(moveAxis, moveAngle);
		m_model.SetRotate(rotate);

		//	前方ベクトルを更新
		m_direction = SimpleMath::Vector3::Transform(SimpleMath::Vector3::Forward, rotate);
		m_direction.Normalize();

	}
	//	前に突進
	else if (m_stateTimer < STATE_TACKLE_BEFORE_TIME + STATE_TACKLE_ATACK_TIME)
	{
		//	前方に移動させる
		Move(m_direction * TACKLE_SPEED, deltaTime);
	}
	//	後隙
	else
	{
		//	全体時間を計算
		float atackTotalTime = 0.0f;
		atackTotalTime += STATE_TACKLE_BEFORE_TIME;
		atackTotalTime += STATE_TACKLE_ATACK_TIME;
		atackTotalTime += STATE_TACKLE_AFTER_TIME;

		//	全体時間を越しているかどうか
		if (m_stateTimer > atackTotalTime)
		{
			//	乱数をもとに次の状態を決める
			int randNum = Random(0, 3);
			if (randNum == 0) { m_stateID = StateID::Shot; }
			else { m_stateID = StateID::Move; }

			//	状態時間を初期化
			m_stateTimer = 0.0f;
		}
	}

射撃行動を作っていく。

それでは続いてStateShot関数に以下のコードを記述してくれ。

	//	弾を8方向に飛ばす
	for (int i = 0; i < SHOT_NUM; i++)
	{
		//	射撃角を算出
		float shotAngle = XM_2PI * (i + 0.5f) / SHOT_NUM;

		//	射撃方向としてとりあえず前方ベクトルを取得する
		SimpleMath::Vector3 shotDirection = m_direction;
		shotDirection.y = 0.0f;
		shotDirection.Normalize();

		//	射撃方向を回転させる
		shotDirection = SimpleMath::Vector3::Transform(
			shotDirection,
			SimpleMath::Matrix::CreateRotationY(shotAngle)
		);
		shotDirection.Normalize();

		//	射撃
		Shot(shotDirection);
	}

	//	乱数をもとに次の状態を決める
	int randNum = Random(0, 3);
	if (randNum == 0) { m_stateID = StateID::Tackle; }
	else { m_stateID = StateID::Move; }

	//	状態時間を初期化
	m_stateTimer = 0.0f;

できたらこんな感じになる。

衝突判定を取っていく

それでは続いて衝突判定を取る機構を作っていく。PlayScene.hに以下の関数を追加してほしい。

プレイヤーと敵から弾を取得できるようにする

Player.hに以下の関数を追加してくれ。

	//	弾を取得
	std::vector<PlayerBullet>* GetBullets() { return &m_bullets; }

Enemy.hにも以下の関数を追加してくれ。

	//	弾を取得
	std::vector<EnemyBullet>* GetBullets() { return &m_bullets; }

衝突判定をとる関数を作る

PlayScene.hに以下の関数を追加しよう。

private:

	//	衝突判定
	void JudgementCollision();

続いてPlayScene.cppに以下の関数を作成しよう。


/// <summary>
/// 衝突判定
/// </summary>
void PlayScene::JudgementCollision()
{
	//	プレイヤーの弾と敵との衝突判定
	std::vector<PlayerBullet>* pPlayerBullets = m_player.GetBullets();
	for (int i = 0; i < pPlayerBullets->size(); i++)
	{
		PlayerBullet* pBullet = &(*pPlayerBullets)[i];

		if (pBullet->GetIsActive() == false) { continue; }
		if (m_enemy.GetIsActive() == false) { continue; }

		const Develop::BoxCollider& enemyCollider = m_enemy.GetCollider();
		const Develop::BoxCollider& bulletCollider = pBullet->GetCollider();

		//	衝突判定を取る
		if (enemyCollider.CheckHitAABB(bulletCollider))
		{
			m_enemy.Damage();
			pBullet->Erace();
		}
	}

	//	敵の弾とプレイヤーとの衝突判定
	std::vector<EnemyBullet>* pEnemyBullets = m_enemy.GetBullets();
	for (int i = 0; i < pEnemyBullets->size(); i++)
	{
		EnemyBullet* pBullet = &(*pEnemyBullets)[i];

		if (pBullet->GetIsActive() == false) { continue; }
		if (m_player.GetIsActive() == false) { continue; }

		const Develop::BoxCollider& playerCollider = m_player.GetCollider();
		const Develop::BoxCollider& bulletCollider = pBullet->GetCollider();

		//	衝突判定を取る
		if (playerCollider.CheckHitAABB(bulletCollider))
		{
			m_player.Dead();
			pBullet->Erace();
		}
	}

	//	プレイヤーと敵との衝突判定
	{
		if (m_player.GetIsActive() == false) { return; }
		if (m_enemy.GetIsActive() == false) { return; }

		const Develop::BoxCollider& playerCollider = m_player.GetCollider();
		const Develop::BoxCollider& enemyCollider = m_enemy.GetCollider();

		//	衝突判定を取る
		if (playerCollider.CheckHitAABB(enemyCollider))
		{
			m_player.Dead();
		}
	}
}

JudgementCollision関数をUpdate関数で呼んであげると衝突判定が取れるようになる。

ダメージリアクションを作ろう

それでは続いてダメージリアクションを作っていこう。Develop::Model3Dを改造していく。Model3D.hが以下のようになるように改造しよう。

#pragma once

//	インクルード達
#include "ResourceManager.h"

namespace Develop
{
	//	前方宣言
	class CameraObject;


	/// <summary>
	/// DirectX::Modelのラッパークラス
	/// </summary>
	class Model3D
	{
	//	ゲッター
	public:

		//	座標の取得
		const DirectX::SimpleMath::Vector3& GetPosition() const { return m_position; }
		//	スケールの取得
		const DirectX::SimpleMath::Vector3& GetScale() const { return m_scale; }
		//	回転の取得
		const DirectX::SimpleMath::Quaternion& GetRotate() const { return m_rotate; }

		//	色
		const DirectX::SimpleMath::Color& GetColor() const { return m_color; }

	//	セッター
	public:

		//	座標の設定
		void SetPosition(const DirectX::SimpleMath::Vector3& position) { m_position = position; }
		//	スケールの設定
		void SetScale(const DirectX::SimpleMath::Vector3& scale) { m_scale = scale; }
		//	回転の設定
		void SetRotate(const DirectX::SimpleMath::Quaternion& rotate) { m_rotate = rotate; }

		//	色
		void SetColor(const DirectX::SimpleMath::Color& color) { m_color = color; }

	//	公開関数
	public:

		//	コンストラクタ
		Model3D();
		//	デストラクタ
		~Model3D() = default;

		//	開始関数
		void Initialize
		(
			ID3D11DeviceContext*		 pDeviceContext	,
			DirectX::CommonStates*		 pCommonStates	,
			ResourceManager::ModelHandle modelHandle
		);

		//	描画関数
		void Render(const CameraObject& camera);

	//	内部パラメータ
	private:

		//	モデルデータ
		ResourceManager::ModelHandle m_pModel;

		DirectX::SimpleMath::Vector3	m_position;	//	座標
		DirectX::SimpleMath::Vector3	m_scale;	//	スケール
		DirectX::SimpleMath::Quaternion m_rotate;	//	回転

		DirectX::SimpleMath::Color m_color;	//	色

		ID3D11DeviceContext*	m_pDeviceContext;	//	デバイスコンテキスト
		DirectX::CommonStates*	m_pCommonStates;	//	共通ステート
	};
}

続いてModel.cppを以下のようになるようにしよう。

#include "pch.h"
#include "Model3D.h"

#include "DeviceResources.h"
#include "CameraObject.h"

//	名前空間の使用
using namespace DirectX;

/// <summary>
/// コンストラクタ
/// </summary>
Develop::Model3D::Model3D()
	:
	m_pDeviceContext(nullptr),
	m_pCommonStates(nullptr),
	m_pModel(nullptr),
	m_scale(SimpleMath::Vector3::One),
	m_color(Colors::White)
{
}

/// <summary>
/// 開始関数
/// </summary>
/// <param name="pDeviceContext">デバイスコンテキストのポインタ</param>
/// <param name="pCommonStatesm">共通ステートのポインタ</param>
/// <param name="pModel">モデルデータ</param>
void Develop::Model3D::Initialize
(
	ID3D11DeviceContext* pDeviceContext,
	DirectX::CommonStates* pCommonStates,
	ResourceManager::ModelHandle modelHandle
)
{
	//	デバイスコンテキストと共通ステートの設定
	m_pDeviceContext = pDeviceContext;
	m_pCommonStates = pCommonStates;

	//	モデルの登録
	m_pModel = modelHandle;
}

/// <summary>
/// 描画関数
/// </summary>
/// <param name="camera">カメラ</param>
void Develop::Model3D::Render(const CameraObject& camera)
{
	//	ワールド行列の作成
	SimpleMath::Matrix world = SimpleMath::Matrix::Identity;
	world *= SimpleMath::Matrix::CreateScale(m_scale);		//	スケール
	world *= SimpleMath::Matrix::CreateFromQuaternion(m_rotate);		//	回転
	world *= SimpleMath::Matrix::CreateTranslation(m_position);	//	座標

	//	エフェクトの更新
	(*m_pModel)->UpdateEffects([&](IEffect* pEffect)
		{
			//	ベーシックエフェクトに変換
			BasicEffect* pBasicEffect = dynamic_cast<BasicEffect*>(pEffect);

			//	変換に成功したかどうか
			if (pBasicEffect != nullptr)
			{
				//	色を設定
				pBasicEffect->SetAmbientLightColor(m_color);
			}
		}
	);

	//	モデルの描画
	(*m_pModel)->Draw
	(
		m_pDeviceContext,
		*m_pCommonStates,
		world,
		camera.GetView(),
		camera.GetProj()
	);
}

これで、モデルの色を変えることができるようになった。
続いてEnemy.cppのRender関数に以下のコードを記述してくれ。

		//	ダメージ効果時間中なら赤色にする
		if (m_damageEffectTimer > 0.0f)
		{
			m_model.SetColor(SimpleMath::Color(Colors::Red));
		}
		else
		{
			m_model.SetColor(SimpleMath::Color(Colors::White));
		}

これらを実装すると完成となる。長い間お疲れ様でした。


この記事が気に入ったらサポートをしてみませんか?