図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;
}