図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();