図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()を実行するタイミングを考える