図1207a
プレイヤーはAボタンでジャンプ、Xボタンで球を発射します。この辺りは前項と同じです。
void FireSphere::OnUpdate() {
auto ptrTrans = GetComponent<Transform>();
if (ptrTrans->GetPosition().y > m_ActiveMaxY) {
float elapsedTime = App::GetApp()->GetElapsedTime();
auto BeforePos = ptrTrans->GetBeforePosition();
auto Pos = ptrTrans->GetPosition();
Pos += m_Velocity * elapsedTime;
ptrTrans->SetPosition(Pos);
auto ptrColl = GetComponent<CollisionSphere>();
auto ptrDraw = GetComponent<BcPNTStaticDraw>();
if (ptrColl->IsSleep()) {
ptrDraw->SetDiffuse(Col4(0.0f, 0.0f, 1.0f, 1.0f));
}
else {
ptrDraw->SetDiffuse(Col4(1.0f, 1.0f, 1.0f, 1.0f));
auto EnemyPtr = GetStage()->GetSharedGameObject<EnemyBox>(L"EnemyBox");
auto BonePtr = GetStage()->GetSharedGameObject<BoneChara>(L"BoneChara");
auto SpherePtr = GetStage()->GetSharedGameObject<EnemySphere>(L"EnemySphere");
Vec3 HitPoint;
TRIANGLE tri;
bool isModelHit = false;
if (EnemyPtr->IsHitSegmentTriangles(BeforePos, Pos, tri, HitPoint)) {
//スパークの放出
auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark");
PtrSpark->InsertSpark(HitPoint);
isModelHit = true;
}
else if (BonePtr->IsHitSegmentTriangles(BeforePos, Pos, tri, HitPoint)) {
//スパークの放出
auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark");
PtrSpark->InsertSpark(HitPoint);
isModelHit = true;
}
else if (SpherePtr->IsHitSegmentTriangles(BeforePos, Pos, tri, HitPoint)) {
//スパークの放出
auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark");
PtrSpark->InsertSpark(HitPoint);
isModelHit = true;
}
if (isModelHit) {
m_Velocity.reflect(tri.GetNormal());
if (m_Velocity.length() > 20.0f) {
m_Velocity.normalize();
m_Velocity *= 20.0f;
}
}
}
}
else {
SetUpdateActive(false);
SetDrawActive(false);
return;
}
}
if (EnemyPtr->IsHitSegmentTriangles(BeforePos, Pos, tri,HitPoint)) {
bool EnemyBox::IsHitSegmentTriangles(const Vec3& StartPos, const Vec3& EndPos, TRIANGLE& tri, Vec3& HitPoint) {
auto ptrColl = GetComponent<CollisionObb>();
OBB obb = ptrColl->GetObb();
SPHERE StartSp;
StartSp.m_Center = StartPos;
StartSp.m_Radius = 0.25f;
SPHERE EndSp;
EndSp.m_Center = EndPos;
EndSp.m_Radius = 0.25f;
SPHERE sp = HitTest::SphereEnclosingSphere(StartSp, EndSp);
Vec3 ret;
if (!HitTest::SPHERE_OBB(sp, obb, ret)) {
//判定前処理
//これにより無駄な判定を避けられる
return false;
}
auto PtrDraw = GetComponent<BcPNTStaticDraw>();
size_t hitIndex;
return PtrDraw->HitTestStaticMeshSegmentTriangles(StartPos, EndPos, HitPoint, tri, hitIndex);
}
if (EnemyPtr->IsHitSegmentTriangles(BeforePos, Pos, tri, HitPoint)) { //スパークの放出 auto PtrSpark = GetStage()->GetSharedGameObject<MultiSpark>(L"MultiSpark"); PtrSpark->InsertSpark(HitPoint); isModelHit = true; }
if (isModelHit) { m_Velocity.reflect(tri.GetNormal()); if (m_Velocity.length() > 20.0f) { m_Velocity.normalize(); m_Velocity *= 20.0f; } }
void FireSphere::OnCollisionEnter(const CollisionPair& Pair) { auto ptrTrans = GetComponent<Transform>(); auto shDest = Pair.m_Dest.lock(); m_Velocity -= shDest->GetVelocity(); m_Velocity.reflect(Pair.m_SrcHitNormal); if (m_Velocity.length() > 20.0f) { m_Velocity.normalize(); m_Velocity *= 20.0f; } }
void FireSphere::OnCollisionExcute(const CollisionPair& Pair) { auto shDest = Pair.m_Dest.lock(); if (shDest->IsFixed()) { //減速 m_Velocity *= 0.95f; if (m_Velocity.length() < 0.05f) { m_Velocity = Vec3(0); } } }
void BallChara::OnUpdate() {
auto bonePtr = GetStage()->GetSharedGameObject<BoneChara>(L"BoneChara");
auto boneTrans = bonePtr->GetComponent<Transform>();
auto boneDraw = bonePtr->GetComponent<BcPNTnTBoneModelDraw>();
auto& bones = boneDraw->GetVecLocalBones();
Mat4x4 mat = bones[2];
auto mesh = boneDraw->GetMeshResource();
vector<Vec3> positions;
mesh->GetLocalPositions(positions);
Mat4x4 localMat;
localMat.translation(positions[1]);
localMat *= mat;
localMat *= boneTrans->GetWorldMatrix();
auto ptrTrans = GetComponent<Transform>();
ptrTrans->SetPosition(localMat.transInMatrix());
ptrTrans->SetQuaternion(localMat.quatInMatrix());
}
localMat.translation(positions[1]); localMat *= mat; localMat *= boneTrans->GetWorldMatrix();
ptrTrans->SetPosition(localMat.transInMatrix()); ptrTrans->SetQuaternion(localMat.quatInMatrix());
図1207b
このサンプルのプレイヤーは、空中でジャンプすることも可能です。球体は大きいですが、球体の上部までジャンプしていって、どこでも削り取ることが可能となっています。
class EnemySphere : public GameObject {
float m_Scale;
Vec3 m_Position;
shared_ptr<MeshResource> m_MeshRes;
public:
//構築と破棄
EnemySphere(const shared_ptr<Stage>& StagePtr,
float Scale,
const Vec3& Position
);
virtual ~EnemySphere();
//初期化
virtual void OnCreate() override;
//操作
bool IsHitSegmentTriangles(const Vec3& StartPos, const Vec3& EndPos, TRIANGLE& tri, Vec3& HitPoint);
bool IsHitSphereTriangles(const SPHERE& StartSp, const SPHERE& EndSp, TRIANGLE& tri, Vec3& HitPoint);
};
void EnemySphere::OnCreate() {
GetStage()->SetSharedGameObject(L"EnemySphere", GetThis<EnemySphere>());
//初期位置などの設定
auto ptrTrans = GetComponent<Transform>();
ptrTrans->SetScale(Vec3(m_Scale));
ptrTrans->SetRotation(Vec3(0));
ptrTrans->SetPosition(m_Position);
//CollisionSphere衝突判定を付ける(Sphere取り出しのため)
auto ptrColl = AddComponent<CollisionSphere>();
//無効にしておく
ptrColl->SetUpdateActive(false);
//描画コンポーネントの設定
auto ptrDraw = AddComponent<BcPNTStaticDraw>();
vector<VertexPositionNormalTexture> vertices;
vector<uint16_t> indices;
MeshUtill::CreateSphere(1.0f, 18, vertices, indices);
m_MeshRes = MeshResource::CreateMeshResource(vertices, indices,true);
ptrDraw->SetMeshResource(m_MeshRes);
//描画するテクスチャを設定
ptrDraw->SetTextureResource(L"WALL_TX");
//影をつける(シャドウマップを描画する)
auto shadowPtr = AddComponent<Shadowmap>();
//影の形(メッシュ)を設定
shadowPtr->SetMeshResource(m_MeshRes);
}
m_MeshRes = MeshResource::CreateMeshResource(vertices, indices,true);
bool EnemySphere::IsHitSphereTriangles(const SPHERE& StartSp, const SPHERE& EndSp, TRIANGLE& tri, Vec3& HitPoint) {
auto ptrColl = GetComponent<CollisionSphere>();
SPHERE sp1 = ptrColl->GetSphere();
SPHERE sp2 = HitTest::SphereEnclosingSphere(StartSp, EndSp);
Vec3 ret;
if (!HitTest::SPHERE_SPHERE(sp1, sp2)) {
//判定前処理
//これにより無駄な判定を避けられる
return false;
}
auto PtrDraw = GetComponent<BcPNTStaticDraw>();
size_t hitIndex;
if (PtrDraw->HitTestStaticMeshSphereTriangles(StartSp, EndSp, HitPoint, tri, hitIndex)) {
//hitindexを頂点のインデックスに換算
hitIndex *= 3;
auto& verVec = m_MeshRes->GetBackupVerteces<VertexPositionNormalTexture>();
vector<uint16_t>& indexVec = m_MeshRes->GetBackupIndices<VertexPositionNormalTexture>();
verVec[indexVec[hitIndex]].position *= 0.95;
verVec[indexVec[hitIndex + 1]].position *= 0.95;
verVec[indexVec[hitIndex + 2]].position *= 0.95;
m_MeshRes->UpdateVirtexBuffer(verVec);
return true;
}
return false;
}
verVec[indexVec[hitIndex]].position *= 0.95; verVec[indexVec[hitIndex + 1]].position *= 0.95; verVec[indexVec[hitIndex + 2]].position *= 0.95;
m_MeshRes->UpdateVirtexBuffer(verVec);