図0109a
//セルマップの作成
void GameStage::CreateStageCellMap() {
auto Group = CreateSharedObjectGroup(L"CellMap");
float PieceSize = 1.0f;
auto Ptr = AddGameObject<StageCellMap>(Vec3(-10.0f, 0, 4.0f),PieceSize,20,7);
//セルマップの区画を表示する場合は以下の設定
Ptr->SetDrawActive(true);
//さらにセルのインデックスとコストを表示する場合は以下の設定
Ptr->SetCellStringActive(true);
SetSharedGameObject(L"StageCellMap1", Ptr);
//グループに追加
Group->IntoGroup(Ptr);
Ptr = AddGameObject<StageCellMap>(Vec3(-10.0f, 0, 16.0f), PieceSize, 20, 7);
//セルマップの区画を表示する場合は以下の設定
Ptr->SetDrawActive(true);
//さらにセルのインデックスとコストを表示する場合は以下の設定
//Ptr->SetCellStringActive(true);
SetSharedGameObject(L"StageCellMap2", Ptr);
//グループに追加
Group->IntoGroup(Ptr);
//以下3つ目のセルマップはグループを別にする
//動的にセルマップを変更する敵用
auto Group2 = CreateSharedObjectGroup(L"CellMap2");
Ptr = AddGameObject<StageCellMap>(Vec3(-10.0f, 0, 28.0f), PieceSize, 20, 7);
//セルマップの区画を表示する場合は以下の設定
Ptr->SetDrawActive(true);
//さらにセルのインデックスとコストを表示する場合は以下の設定
Ptr->SetCellStringActive(true);
SetSharedGameObject(L"StageCellMap3", Ptr);
//グループに追加
Group2->IntoGroup(Ptr);
}
auto Group = CreateSharedObjectGroup(L"CellMap");
float PieceSize = 1.0f;
auto Ptr = AddGameObject<StageCellMap>(Vec3(-10.0f, 0, 4.0f),PieceSize,20,7);
//セルマップの区画を表示する場合は以下の設定
Ptr->SetDrawActive(true);
//さらにセルのインデックスとコストを表示する場合は以下の設定
Ptr->SetCellStringActive(true);
SetSharedGameObject(L"StageCellMap1", Ptr);
//グループに追加
Group->IntoGroup(Ptr);
void GameStage::OnCreate() {
try {
//リソースの作成
CreateResourses();
//ビューとライトの作成
CreateViewLight();
//プレートの作成
CreatePlate();
//セルマップの作成
CreateStageCellMap();
//固定のボックスの作成
CreateFixedBox();
//プレーヤーの作成
CreatePlayer();
//敵の作成
CreateEnemy();
}
catch (...) {
throw;
}
}
void FixedBox::OnCreate() {
auto PtrTransform = GetComponent<Transform>();
PtrTransform->SetScale(m_Scale);
PtrTransform->SetRotation(m_Rotation);
PtrTransform->SetPosition(m_Position);
//衝突判定
auto PtrObb = AddComponent<CollisionObb>();
PtrObb->SetFixed(true);
//影をつける
auto ShadowPtr = AddComponent<Shadowmap>();
ShadowPtr->SetMeshResource(L"DEFAULT_CUBE");
auto PtrDraw = AddComponent<PNTStaticDraw>();
PtrDraw->SetMeshResource(L"DEFAULT_CUBE");
PtrDraw->SetOwnShadowActive(true);
PtrDraw->SetTextureResource(L"SKY_TX");
}
//衝突判定
auto PtrObb = AddComponent<CollisionObb>();
PtrObb->SetFixed(true);
//固定のボックスの作成
void GameStage::CreateFixedBox() {
//配列の初期化
vector< vector > Vec = {
{
Vec3(1.0f, 0.5f, 40.0f),
Vec3(0.0f, 0.0f, 0.0f),
Vec3(9.5f, 0.25f, 20.0f)
},
//中略
};
//ボックスのグループを作成
auto BoxGroup = CreateSharedObjectGroup(L"FixedBoxes");
//オブジェクトの作成
for (auto v : Vec) {
auto BoxPtr = AddGameObject(v[0], v[1], v[2]);
//ボックスのグループに追加
BoxGroup->IntoGroup(BoxPtr);
}
//最初の2つのセルマップへのボックスのコスト設定
SetCellMapCost(L"CellMap");
//奥のセルマップへのボックスのコスト設定
SetCellMapCost(L"CellMap2");
}
//固定のボックスのコストをセルマップに反映
void GameStage::SetCellMapCost(const wstring& CellMapGroupName) {
//セルマップ内にFixedBoxの情報をセット
auto Group = GetSharedObjectGroup(CellMapGroupName);
auto BoxGroup = GetSharedObjectGroup(L"FixedBoxes");
//セルマップグループを取得
for (auto& gv : Group->GetGroupVector()) {
auto MapPtr = dynamic_pointer_cast<StageCellMap>(gv.lock());
if (MapPtr) {
//セルマップからセルの配列を取得
auto& CellVec = MapPtr->GetCellVec();
//ボックスグループからボックスの配列を取得
auto& BoxVec = BoxGroup->GetGroupVector();
vector<AABB> ObjectsAABBVec;
for (auto& v : BoxVec) {
auto FixedBoxPtr = dynamic_pointer_cast<FixedBox>(v.lock());
if (FixedBoxPtr) {
auto ColPtr = FixedBoxPtr->GetComponent<CollisionObb>();
//ボックスの衝突判定かラッピングするAABBを取得して保存
ObjectsAABBVec.push_back(ColPtr->GetWrappingAABB());
}
}
//セル配列からセルをスキャン
for (auto& v : CellVec) {
for (auto& v2 : v) {
for (auto& vObj : ObjectsAABBVec) {
if (HitTest::AABB_AABB_NOT_EQUAL(v2.m_PieceRange, vObj)) {
//ボックスのABBとNOT_EQUALで衝突判定
v2.m_Cost = -1;
break;
}
}
}
}
}
}
}
//--------------------------------------------------------------------------------------
/// デフォルトステート
//--------------------------------------------------------------------------------------
class EnemyDefault : public ObjState<Enemy>
{
EnemyDefault() {}
public:
//ステートのインスタンス取得
DECLARE_SINGLETON_INSTANCE(EnemyDefault)
virtual void Enter(const shared_ptr<Enemy>& Obj)override;
virtual void Execute(const shared_ptr<Enemy>& Obj)override;
virtual void Exit(const shared_ptr<Enemy>& Obj)override;
};
//--------------------------------------------------------------------------------------
/// プレイヤーを追いかけるステート
//--------------------------------------------------------------------------------------
class EnemySeek : public ObjState<Enemy>
{
EnemySeek() {}
public:
//ステートのインスタンス取得
DECLARE_SINGLETON_INSTANCE(EnemySeek)
virtual void Enter(const shared_ptr<Enemy>& Obj)override;
virtual void Execute(const shared_ptr<Enemy>& Obj)override;
virtual void Exit(const shared_ptr<Enemy>& Obj)override;
};
//ステートのインスタンス取得
DECLARE_SINGLETON_INSTANCE(EnemyDefault)
static shared_ptr<EnemyDefault> Instance();
//--------------------------------------------------------------------------------------
/// デフォルトステート
//--------------------------------------------------------------------------------------
//ステートのインスタンス取得
IMPLEMENT_SINGLETON_INSTANCE(EnemyDefault)
void EnemyDefault::Enter(const shared_ptr<Enemy>& Obj) {
}
void EnemyDefault::Execute(const shared_ptr<Enemy>& Obj) {
if (!Obj->DefaultBehavior()) {
Obj->GetStateMachine()->ChangeState(EnemySeek::Instance());
}
}
void EnemyDefault::Exit(const shared_ptr<Enemy>& Obj) {
}
//--------------------------------------------------------------------------------------
/// プレイヤーを追いかけるステート
//--------------------------------------------------------------------------------------
//ステートのインスタンス取得
IMPLEMENT_SINGLETON_INSTANCE(EnemySeek)
void EnemySeek::Enter(const shared_ptr<Enemy>& Obj) {
auto PtrSeek = Obj->GetComponent<SeekSteering>();
PtrSeek->SetUpdateActive(true);
}
void EnemySeek::Execute(const shared_ptr<Enemy>& Obj) {
if (!Obj->SeekBehavior()) {
Obj->GetStateMachine()->ChangeState(EnemyDefault::Instance());
}
}
void EnemySeek::Exit(const shared_ptr<Enemy>& Obj) {
auto PtrSeek = Obj->GetComponent<SeekSteering>();
PtrSeek->SetUpdateActive(false);
}
//ステートのインスタンス取得
IMPLEMENT_SINGLETON_INSTANCE(EnemyDefault)
shared_ptr<EnemyDefault> EnemyDefault::Instance() { static shared_ptr<EnemyDefault> instance; if(!instance) { instance = shared_ptr<EnemyDefault>(new EnemyDefault); } return instance; }
//--------------------------------------------------------------------------------------
// 敵
//--------------------------------------------------------------------------------------
class Enemy : public GameObject {
protected:
weak_ptr<StageCellMap> m_CelMap;
Vec3 m_Scale;
Vec3 m_StartRotation;
Vec3 m_StartPosition;
vector<CellIndex> m_CellPath;
//現在の自分のセルインデックス
int m_CellIndex;
//めざす(次の)のセルインデックス
int m_NextCellIndex;
//ターゲットのセルインデックス
int m_TargetCellIndex;
shared_ptr<StateMachine<Enemy>> m_StateMachine;
//進行方向を向くようにする
void RotToHead();
public:
//構築と破棄
Enemy(const shared_ptr<Stage>& StagePtr,
const shared_ptr<StageCellMap>& CellMap,
const Vec3& Scale,
const Vec3& Rotation,
const Vec3& Position
);
virtual ~Enemy();
//プレイヤーの検索
bool SearchPlayer();
//デフォルト行動
virtual bool DefaultBehavior();
//Seek行動
bool SeekBehavior();
//アクセサ
shared_ptr< StateMachine<Enemy> > GetStateMachine() const {
return m_StateMachine;
}
//初期化
virtual void OnCreate() override;
//操作
virtual void OnUpdate() override;
virtual void OnUpdate2() override;
};
weak_ptr<StageCellMap> m_CelMap;
void Enemy::OnCreate() {
auto PtrTransform = GetComponent<Transform>();
PtrTransform->SetPosition(m_StartPosition);
PtrTransform->SetScale(m_Scale);
PtrTransform->SetRotation(m_StartRotation);
//重力をつける
auto PtrGravity = AddComponent<Gravity>();
//Rigidbodyをつける
auto PtrRigid = AddComponent<Rigidbody>();
//反発係数は0.5(半分)
PtrRigid->SetReflection(0.5f);
auto PtrSeek = AddComponent<SeekSteering>();
PtrSeek->SetUpdateActive(false);
//パス検索
auto MapPtr = m_CelMap.lock();
if (!MapPtr) {
throw BaseException(
L"セルマップが不定です",
L"if (!MapPtr) ",
L" Enemy::OnCreate()"
);
}
auto PathPtr = AddComponent<PathSearch>(MapPtr);
//SPの衝突判定をつける
auto PtrColl = AddComponent<CollisionSphere>();
PtrColl->SetIsHitAction(IsHitAction::AutoOnParent);
//影をつける
auto ShadowPtr = AddComponent<Shadowmap>();
ShadowPtr->SetMeshResource(L"DEFAULT_SPHERE");
auto PtrDraw = AddComponent<PNTStaticDraw>();
PtrDraw->SetMeshResource(L"DEFAULT_SPHERE");
PtrDraw->SetTextureResource(L"TRACE2_TX");
//透明処理をする
SetAlphaActive(true);
m_StateMachine = make_shared<StateMachine<Enemy>>(GetThis<Enemy>());
m_StateMachine->ChangeState(EnemyDefault::Instance());
}
//パス検索
auto MapPtr = m_CelMap.lock();
if (!MapPtr) {
throw BaseException(
L"セルマップが不定です",
L"if (!MapPtr) ",
L" Enemy::OnCreate()"
);
}
auto PathPtr = AddComponent<PathSearch>(MapPtr);
m_StateMachine = make_shared<StateMachine<Enemy>>(GetThis<Enemy>());
m_StateMachine->ChangeState(EnemyDefault::Instance());
void Enemy::OnUpdate() {
//ステートマシンのUpdateを行う
//この中でステートの切り替えが行われる
m_StateMachine->Update();
}
bool Enemy::DefaultBehavior() {
auto PtrRigid = GetComponent<Rigidbody>();
auto Velo = PtrRigid->GetVelocity();
Velo *= 0.95f;
PtrRigid->SetVelocity(Velo);
auto MapPtr = m_CelMap.lock();
if (MapPtr) {
auto PlayerPtr = GetStage()->GetSharedGameObject<Player>(L"Player");
auto PlayerPos = PlayerPtr->GetComponent<Transform>()->GetPosition();
CellIndex PlayerCell;
if (MapPtr->FindCell(PlayerPos, PlayerCell)) {
return false;
}
}
return true;
}
MapPtr->FindCell(PlayerPos, PlayerCell)
bool Enemy::SeekBehavior() {
auto PlayerPtr = GetStage()->GetSharedGameObject<Player>(L"Player");
auto PlayerPos = PlayerPtr->GetComponent<Transform>()->GetPosition();
auto MapPtr = m_CelMap.lock();
if (MapPtr) {
if (SearchPlayer()) {
auto PtrSeek = GetComponent<SeekSteering>();
if (m_NextCellIndex == 0) {
//中略
}
else {
//中略
}
return true;
}
else {
//中略
}
}
return false;
}
bool Enemy::SearchPlayer() {
auto MapPtr = m_CelMap.lock();
if (MapPtr) {
auto PathPtr = GetComponent<PathSearch>();
auto PlayerPtr = GetStage()->GetSharedGameObject<Player>(L"Player");
auto PlayerPos = PlayerPtr->GetComponent<Transform>()->GetPosition();
m_CellPath.clear();
//パス検索をかける
if (PathPtr->SearchCell(PlayerPos, m_CellPath)) {
//検索が成功した
m_CellIndex = 0;
m_TargetCellIndex = m_CellPath.size() - 1;
if (m_CellIndex == m_TargetCellIndex) {
//すでに同じセルにいる
m_NextCellIndex = m_CellIndex;
}
else {
//離れている
m_NextCellIndex = m_CellIndex + 1;
}
return true;
}
else {
//失敗した
m_CellIndex = -1;
m_NextCellIndex = -1;
m_TargetCellIndex = -1;
}
}
return false;
}