図1401a
この章は1102.物理計算を使った3Dの配置に紹介した物理的処理(Rigidbodyコンポーネント)をゲームにどのように反映していくか、のサンプルです。
図1401b
その状態で、Yボタンを押し続けると、選択されたオブジェクトが、プレイヤーの上部に引き寄せられます。Yボタンを離すと、そのオブジェクトは落ちてきます。場合によってはプレイヤーの頭から落ちてくる場合もあるので注意しましょう。(だからといってプレイヤーに何か損害が出るわけではないですが・・・)
図1401c
void FireSphere::OnCreate() {
auto ptrTrans = GetComponent<Transform>();
ptrTrans->SetScale(Vec3(m_Scale));
ptrTrans->SetQuaternion(Quat());
ptrTrans->SetPosition(m_Emitter);
//コリジョンを付ける(ボリューム取得のため)
auto ptrColl = AddComponent<CollisionSphere>();
ptrColl->SetAfterCollision(AfterCollision::None);
//影をつける
auto ptrShadow = AddComponent<Shadowmap>();
ptrShadow->SetMeshResource(L"DEFAULT_SPHERE");
auto ptrDraw = AddComponent<BcPNTStaticDraw>();
ptrDraw->SetFogEnabled(true);
ptrDraw->SetMeshResource(L"DEFAULT_SPHERE");
ptrDraw->SetTextureResource(L"SKY_TX");
GetStage()->SetSharedGameObject(L"FireSphere", GetThis<GameObject>());
}
//Xボタンハンドラ
void Player::OnPushX() {
auto Ptr = GetComponent<Transform>();
Vec3 Pos = Ptr->GetPosition();
Pos.y += 0.5f;
Quat Qt = Ptr->GetQuaternion();
Vec3 Rot = Qt.toRotVec();
float RotY = Rot.y;
Vec3 velo(sin(RotY), 0.05f, cos(RotY));
velo.normalize();
velo *= 20.0f;
auto ShPtr = GetStage()->GetSharedGameObject<FireSphere>(L"FireSphere",false);
if (ShPtr) {
ShPtr->Reset(Pos, velo);
}
else {
GetStage()->AddGameObject<FireSphere>(Pos, velo);
}
}
void FireSphere::OnUpdate() { auto ptrTrans = GetComponent<Transform>(); if (ptrTrans->GetPosition().y > -20.0f) { float elapsedTime = App::GetApp()->GetElapsedTime(); Vec3 Ac = Vec3(0, -9.8f, 0) * 1.0f; m_Velocity += Ac * elapsedTime; auto Pos = ptrTrans->GetPosition(); Pos += m_Velocity * elapsedTime; ptrTrans->SetPosition(Pos); } else { //じっとしている ptrTrans->SetPosition(Vec3(0, -20.0f, 0)); return; } auto ptrColl = GetComponent<CollisionSphere>(); //物理オブジェクトを持つ配列の取得 vector<shared_ptr<Rigidbody>> PsComptVec; GetStage()->GetUsedDynamicCompoentVec<Rigidbody>(PsComptVec); for (auto& v : PsComptVec) { auto ptrG = dynamic_pointer_cast<ActivePsObject>(v->GetGameObject()); if (ptrG) { auto ptrRegSp = dynamic_pointer_cast<RigidbodySphere>(v); auto ptrRegBox = dynamic_pointer_cast<RigidbodyBox>(v); auto ptrRegCap = dynamic_pointer_cast<RigidbodyCapsule>(v); bool hold = false; if (ptrRegSp) { if (HitTest::SPHERE_SPHERE(ptrRegSp->GetSPHERE(), ptrColl->GetSphere())) { hold = true; } } else if (ptrRegBox) { Vec3 ret; if (HitTest::SPHERE_OBB(ptrColl->GetSphere(), ptrRegBox->GetOBB(), ret)) { hold = true; } } else if (ptrRegCap) { Vec3 ret; if (HitTest::SPHERE_CAPSULE(ptrColl->GetSphere(), ptrRegCap->GetCAPSULE(), ret)) { hold = true; } } if (hold) { auto ptrHold = m_HoldObject.lock(); if (ptrHold) { ptrHold->SetHold(false); } m_HoldObject = ptrG; ptrG->SetHold(true); ptrTrans->ResetPosition(Vec3(0, -20, 0)); break; } } } }
if (ptrTrans->GetPosition().y > -20.0f) { float elapsedTime = App::GetApp()->GetElapsedTime(); Vec3 Ac = Vec3(0, -9.8f, 0) * 1.0f; m_Velocity += Ac * elapsedTime; auto Pos = ptrTrans->GetPosition(); Pos += m_Velocity * elapsedTime; ptrTrans->SetPosition(Pos); } else { //じっとしている ptrTrans->SetPosition(Vec3(0, -20.0f, 0)); return; }
//物理オブジェクトを持つ配列の取得
vector<shared_ptr<Rigidbody>> PsComptVec;
GetStage()->GetUsedDynamicCompoentVec<PsBodyComponent>(PsComptVec);
for (auto& v : PsComptVec) { auto ptrG = dynamic_pointer_cast<ActivePsObject>(v->GetGameObject()); if (ptrG) { auto ptrRegSp = dynamic_pointer_cast<RigidbodySphere>(v); auto ptrRegBox = dynamic_pointer_cast<RigidbodyBox>(v); auto ptrRegCap = dynamic_pointer_cast<RigidbodyCapsule>(v); bool hold = false; if (ptrRegSp) { if (HitTest::SPHERE_SPHERE(ptrRegSp->GetSPHERE(), ptrColl->GetSphere())) { hold = true; } } else if (ptrRegBox) { Vec3 ret; if (HitTest::SPHERE_OBB(ptrColl->GetSphere(), ptrRegBox->GetOBB(), ret)) { hold = true; } } else if (ptrRegCap) { Vec3 ret; if (HitTest::SPHERE_CAPSULE(ptrColl->GetSphere(), ptrRegCap->GetCAPSULE(), ret)) { hold = true; } } if (hold) { auto ptrHold = m_HoldObject.lock(); if (ptrHold) { ptrHold->SetHold(false); } m_HoldObject = ptrG; ptrG->SetHold(true); ptrTrans->ResetPosition(Vec3(0, -20, 0)); break; } } }
ptrHold->SetHold(false);
ptrG->SetHold(true);
ptrTrans->ResetPosition(Vec3(0, -20, 0));
void ActivePsObject::SetHold(bool b) {
if (b) {
if (m_StateMachine->GetCurrentState() == ActivePsDefaultState::Instance()) {
m_StateMachine->ChangeState(ActivePsHoldState::Instance());
//プレイヤーに自分がホールドされていることを伝える
auto ptrPlayer = GetStage()->GetSharedGameObject<Player>(L"Player", false);
if (ptrPlayer) {
ptrPlayer->SetHoldObject(GetThis<ActivePsObject>());
}
}
}
else {
if (m_StateMachine->GetCurrentState() == ActivePsHoldState::Instance()) {
m_StateMachine->ChangeState(ActivePsDefaultState::Instance());
}
}
}
//Yボタンハンドラ(押した瞬間) void Player::OnPushY() { //ホールドしたオブジェクトがなければ何もしない auto ptrHold = m_HoldObject.lock(); if (!ptrHold) { return; } auto ptrActionLine = m_ActionLine.lock(); if (ptrActionLine) { auto Check = ptrActionLine->GetEndObj(); auto CheckHold = dynamic_pointer_cast<GameObject>(ptrHold); if (Check != CheckHold) { ptrActionLine->SetEndObj(ptrHold); } ptrActionLine->SetDrawActive(true); } else { //ラインの作成 auto ptrLine = GetStage()->AddGameObject<ActionLine>(GetThis<GameObject>(), ptrHold); ptrLine->SetDrawActive(true); m_ActionLine = ptrLine; } }
//ラインの作成 auto ptrLine = GetStage()->AddGameObject<ActionLine>(GetThis<GameObject>(), ptrHold);
//Yボタンハンドラ(離した瞬間) void Player::OnReleaseY() { auto ptrActionLine = m_ActionLine.lock(); if (ptrActionLine) { ptrActionLine->SetDrawActive(false); } }
//Yボタンハンドラ(押し続け)
void Player::OnPressY() {
auto ptrTrans = GetComponent<Transform>();
auto playerPos = ptrTrans->GetPosition();
auto ptrHold = m_HoldObject.lock();
if (ptrHold) {
auto ptrPs = ptrHold->GetDynamicComponent<RigidbodySingle>(false);
if (ptrPs) {
auto psPos = ptrPs->GetPosition();
float toY = 2.0f;
if (psPos.y > 5.0f) {
toY = 0.0f;
}
psPos.y = 0;
playerPos.y = 0;
Vec3 toPlayerVec = playerPos - psPos;
ptrPs->WakeUp();
ptrPs->SetLinearVelocity(Vec3(toPlayerVec.x, toY, toPlayerVec.z));
}
}
}
ptrPs->WakeUp();