図0307a
手前と奥のほうで、固定ボックスが2つづつ(合計4つ)並んでいます。プレイヤーを動かし、手前の2つ並んでいるボックスに乗ってみます。そしてボックス上で移動すると、2つのボックスの境界のあたりで、引っかかる感覚があると思います。<?xml version="1.0" encoding="utf-8" ?> <GameStage> <GameObject Type="TilingPlate" Scale="40,40,1" Rot="XM_PIDIV2,0,0" Pos="0,0,0" UPic="1.0" VPic="1.0" /> <GameObject Type="TilingFixedBox" Scale="40,1,1" Rot="0,0,0" Pos="0,0.5,19.5" UPic="1.0" VPic="1.0" /> <GameObject Type="TilingFixedBox" Scale="40,1,1" Rot="0,0,0" Pos="0,0.5,-19.5" UPic="1.0" VPic="1.0" /> <GameObject Type="TilingFixedBox" Scale="40,1,1" Rot="0,XM_PIDIV2,0" Pos="19.5,0.5,0" UPic="1.0" VPic="1.0" /> <GameObject Type="TilingFixedBox" Scale="40,1,1" Rot="0,XM_PIDIV2,0" Pos="-19.5,0.5,0" UPic="1.0" VPic="1.0" /> <GameObject Type="FrameBox" Scale="5.0f, 0.5f, 2.0f" Rot="0,0,0" Pos="-2.5,0.25,5.0" AddTag="false" /> <GameObject Type="FrameBox" Scale="5.0f, 0.5f, 2.0f" Rot="0,0,0" Pos="2.5,0.25,5.0" AddTag="false" /> <GameObject Type="FrameBox" Scale="5.0f, 0.5f, 2.0f" Rot="0,0,0" Pos="-2.5,0.25,10.0" AddTag="true" /> <GameObject Type="FrameBox" Scale="5.0f, 0.5f, 2.0f" Rot="0,0,0" Pos="2.5,0.25,10.0" AddTag="true" /> </GameStage>
FrameBox::FrameBox(const shared_ptr<Stage>& StagePtr, IXMLDOMNodePtr pNode) : GameObject(StagePtr) { try { auto ScaleStr = XmlDocReader::GetAttribute(pNode, L"Scale"); auto RotStr = XmlDocReader::GetAttribute(pNode, L"Rot"); auto PosStr = XmlDocReader::GetAttribute(pNode, L"Pos"); auto AddTagStr = XmlDocReader::GetAttribute(pNode, L"AddTag"); //トークン(カラム)の配列 vector<wstring> Tokens; //トークン(カラム)単位で文字列を抽出(L','をデリミタとして区分け) Tokens.clear(); Util::WStrToTokenVector(Tokens, ScaleStr, L','); //各トークン(カラム)をスケール、回転、位置に読み込む m_Scale = Vec3( (float)_wtof(Tokens[0].c_str()), (float)_wtof(Tokens[1].c_str()), (float)_wtof(Tokens[2].c_str()) ); Tokens.clear(); Util::WStrToTokenVector(Tokens, RotStr, L','); //回転は「XM_PIDIV2」の文字列になっている場合がある m_Rotation.x = (Tokens[0] == L"XM_PIDIV2") ? XM_PIDIV2 : (float)_wtof(Tokens[0].c_str()); m_Rotation.y = (Tokens[1] == L"XM_PIDIV2") ? XM_PIDIV2 : (float)_wtof(Tokens[1].c_str()); m_Rotation.z = (Tokens[2] == L"XM_PIDIV2") ? XM_PIDIV2 : (float)_wtof(Tokens[2].c_str()); Tokens.clear(); Util::WStrToTokenVector(Tokens, PosStr, L','); m_Position = Vec3( (float)_wtof(Tokens[0].c_str()), (float)_wtof(Tokens[1].c_str()), (float)_wtof(Tokens[2].c_str()) ); if (AddTagStr == L"true") { AddTag(L"FrameBox"); } } catch (...) { throw; } }
class Player : public GameObject { //中略 //FrameBoxに乗っているかどうか bool m_IsOnFrameBox; public: //中略 //-------------------------------------------------------------------------------------- /*! @brief フレームボックスに乗ってるかどうか @return フレームボックスに乗ってればtrue */ //-------------------------------------------------------------------------------------- bool IsOnFrameBox()const { return m_IsOnFrameBox; } //中略 };
//衝突検知時
void Player::OnCollision(vector<shared_ptr<GameObject>>& OtherVec) {
//プレイヤーが何かに当たった
if (GetStateMachine()->GetCurrentState() == PlayerJumpState::Instance()) {
//現在がジャンプステートならPlayerDefaultに設定
GetStateMachine()->ChangeState(PlayerDefaultState::Instance());
}
for (auto& v : OtherVec) {
if (v->FindTag(L"FrameBox")) {
auto PtrSrcColl = GetComponent<CollisionSphere>();
auto PtrDestColl = v->GetComponent<CollisionObb>();
Vec3 RetVec;
PtrSrcColl->GetHitNormal(PtrDestColl, RetVec);
RetVec.normalize();
Vec3 angle(XMVector3AngleBetweenVectors(RetVec, Vec3(0, -1.0f, 0)));
if (angle.x <= 0.01f) {
GetComponent<Collision>()->SetIsHitAction(IsHitAction::None);
m_IsOnFrameBox = true;
return;
}
}
}
}
void Player::OnUpdate2() {
//文字列の表示
DrawStrings();
if (m_IsOnFrameBox && GetComponent<Collision>()->GetHitObjectVec().empty()) {
GetComponent<Collision>()->SetIsHitAction(IsHitAction::Auto);
m_IsOnFrameBox = false;
}
}
// void PlayerDefaultState::Execute(const shared_ptr<Player>& Obj) { auto PtrBehavior = Obj->GetBehavior<PlayerBehavior>(); PtrBehavior->MovePlayer(); if (!Obj->IsOnFrameBox()) { auto PtrGrav = Obj->GetBehavior<Gravity>(); PtrGrav->Execute(); } } // void PlayerJumpState::Execute(const shared_ptr<Player>& Obj) { //ジャンプ中も方向変更可能 auto PtrBehavior = Obj->GetBehavior<PlayerBehavior>(); PtrBehavior->MovePlayer(); if (!Obj->IsOnFrameBox()) { auto PtrGrav = Obj->GetBehavior<Gravity>(); PtrGrav->Execute(); } }
1、つながっているオブジェクトを特定する(AddTagで処理) 2、コリジョンのSetIsHitAction(IsHitAction::None)の設定と復帰のタイミングを考える 3、重力のPtrGrav->Execute()を実行するタイミングを考える