void CSprite::Draw(CRenderContext& renderContext) { CMatrix mWorld; mWorld = CMatrix::Identity; CVector3 scale; int frameBufferW = Engine().GetFrameBufferWidth(); int frameBufferH = Engine().GetFrameBufferHeight(); int frameBufferHalfW = frameBufferW / 2; int framebufferHalfH = frameBufferH / 2; scale.x = m_size.x / frameBufferW; scale.y = m_size.y / frameBufferH; scale.z = 1.0f; mWorld.MakeScaling(scale); CMatrix mTrans = CMatrix::Identity; CVector3 trans; trans.x = m_pos.x / frameBufferHalfW; trans.y = m_pos.y / framebufferHalfH; trans.z = 0.0f; //ピボットの分のオフセットを計算。 CVector3 pivotOffset; pivotOffset.x = (m_size.x * (0.5f - m_pivot.x)) / frameBufferHalfW; pivotOffset.y = (m_size.y * (0.5f - m_pivot.y)) / framebufferHalfH; pivotOffset.z = 0.0f; trans.Add(pivotOffset); mTrans.MakeTranslation(trans); CMatrix mRot; mRot.MakeRotationFromQuaternion(m_rotation); mWorld.Mul(mRot, mWorld); mWorld.Mul(mWorld, mTrans); renderContext.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); renderContext.SetRenderState(D3DRS_SRCBLEND, BLEND_SRCALPHA); renderContext.SetRenderState(D3DRS_DESTBLEND, BLEND_INVSRCALPHA); m_effect->Begin(renderContext); m_effect->BeginPass(renderContext, 0); m_effect->SetTechnique(renderContext, "SpriteTexture"); m_effect->SetValue(renderContext, "mWorld", &mWorld, sizeof(mWorld)); m_effect->SetTexture(renderContext, "g_tex", m_texture); m_effect->SetValue(renderContext, "uvRect", &m_uvRect, sizeof(m_uvRect)); m_effect->SetValue(renderContext, "alpha", &m_alpha, sizeof(m_alpha)); m_effect->CommitChanges(renderContext); renderContext.SetVertexDeclaration(m_primitive.GetVertexDecl()); renderContext.SetStreamSource(0, m_primitive.GetVertexBuffer()); renderContext.SetIndices(m_primitive.GetIndexBuffer()); renderContext.DrawIndexedPrimitive(&m_primitive); m_effect->EndPass(renderContext); m_effect->End(renderContext); renderContext.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); }
/*! * @brief 更新。 */ void CShadowMap::Update() { if (m_isEnable) { //ライトビュープロジェクション行列を作成。 CVector3 lightUp; float t = fabsf(m_lightDirection.Dot(CVector3::AxisY)); if (fabsf((t - 1.0f)) < 0.00001f) { //ライトの方向がほぼY軸と並行。 lightUp = CVector3::AxisX; } else { lightUp = CVector3::AxisY; } //ライトからみたビュー行列を作成。 CVector3 target; target.Add(m_lightPosition, m_lightDirection); m_lvMatrix.MakeLookAt(m_lightPosition, target, lightUp); m_LVPMatrix.Mul(m_lvMatrix, m_projectionMatrix); } }
/*! * @brief 衝突検出と解決。 *@param[in] nextPosition 次の座標。 */ void EnemyTest::CollisionDetectAndResolve(CVector3 nextPosition) { //XZ平面を調べる。 { int loopCount = 0; while (true) { CVector3 addPos; addPos.Subtract(nextPosition, position); CVector3 posTmp = position; posTmp.y += radius + 0.2f; btTransform start, end; start.setIdentity(); end.setIdentity(); start.setOrigin(*(btVector3*)(&posTmp)); CVector3 newPos; SweepResultWall callback; callback.startPos = position; CVector3 addPosXZ = addPos; addPosXZ.y = 0.0f; if (addPosXZ.Length() > 0.0001f) { newPos.Add(posTmp, addPosXZ); end.setOrigin(btVector3(newPos.x, newPos.y, newPos.z)); PhysicsWorld().ConvexSweepTest((const btConvexShape*)collider.GetBody(), start, end, callback); } if (callback.isHit) { //当たった。 float t = fabsf(acosf(callback.hitNormal.Dot(CVector3::Up))); if (t >= CMath::PI * 0.3f) { //壁。 nextPosition.x = callback.hitPos.x; nextPosition.z = callback.hitPos.z; //半径分押し戻す。 CVector3 hitNormalXZ = callback.hitNormal; hitNormalXZ.y = 0.0f; hitNormalXZ.Normalize(); CVector3 t = hitNormalXZ; t.Scale(radius); nextPosition.Add(t); //続いて壁に沿って滑らせる。 t.Cross(hitNormalXZ, CVector3::Up); t.Normalize(); //押し戻しで動いた分は減算する。 CVector3 t2; t2.Subtract(nextPosition, position); t2.y = 0.0f; addPosXZ.Subtract(t2); t.Scale(t.Dot(addPosXZ)); nextPosition.Add(t); } } else { //どことも当たらないので終わり。 break; } loopCount++; if (loopCount == 5) { break; } } } //下方向を調べる。 { CVector3 addPos; addPos.Subtract(nextPosition, position); btTransform start, end; start.setIdentity(); end.setIdentity(); start.setOrigin(btVector3(position.x, position.y + radius, position.z)); CVector3 newPos; SweepResultGround callback; callback.startPos = position; if (addPos.y < 0.0f) { newPos = (*(CVector3*)&start.getOrigin()); newPos.y += addPos.y; end.setOrigin(btVector3(newPos.x, newPos.y, newPos.z)); PhysicsWorld().ConvexSweepTest((const btConvexShape*)collider.GetBody(), start, end, callback); } if (callback.isHit) { //当たった。 float t = fabsf(acosf(callback.hitNormal.Dot(CVector3::Up))); if (t < CMath::PI * 0.3f) { //地面。 CVector3 Circle; float x = 0.0f; float offset = 0.0f; //押し戻す量。 Circle = CVector3::Zero; Circle = position; Circle.y = callback.hitPos.y;//円の中心 CVector3 v; v.Subtract(Circle, callback.hitPos); x = v.Length();//物体の角とプレイヤーの間の横幅の距離が求まる。 offset = sqrt(max(0.0f, radius*radius - x*x));//yの平方根を求める。 moveSpeed.y = 0.0f; isJump = false; nextPosition.y = callback.hitPos.y + offset - radius; } } } position = nextPosition; }
void EnemyTest::Update() { CVector3 nextPosition = position; const float MOVE_SPEED = 5.0f; if (state == enStateRun || state == enStateStand) { if (Pad(0).IsTrigger(enButtonRB3)) { isPointLightOn = !isPointLightOn; } if (Pad(0).IsPress(enButtonA)) { //Aボタンが押された。 //車との距離を調べる。 CVector3 diff = g_car->GetPosition(); diff.Subtract(position); if (diff.Length() < 2.0f) { //車との距離が2m以内。 state = enState_RideOnCar; skinModel.SetShadowReceiverFlag(false); skinModel.SetShadowCasterFlag(false); g_car->SetRideOnFlag(true); g_camera->SetCar(g_car); return; } else if(!isJump){ //車との距離が離れていたらジャンプ。 moveSpeed.y = 8.0f; isJump = true; } } //走りか立ち状態の時。 CVector3 moveDirLocal; moveDirLocal.y = 0.0f; moveDirLocal.x = Pad(0).GetLStickXF(); moveDirLocal.z = Pad(0).GetLStickYF(); const CMatrix& mViewInv = g_camera->GetCamera().GetViewMatrixInv(); //カメラ空間から見た奥方向のベクトルを取得。 CVector3 cameraZ; cameraZ.x = mViewInv.m[2][0]; cameraZ.y = 0.0f; //Y軸いらない。 cameraZ.z = mViewInv.m[2][2]; cameraZ.Normalize(); //Y軸を打ち消しているので正規化する。 //カメラから見た横方向のベクトルを取得。 CVector3 cameraX; cameraX.x = mViewInv.m[0][0]; cameraX.y = 0.0f; //Y軸はいらない。 cameraX.z = mViewInv.m[0][2]; cameraX.Normalize(); //Y軸を打ち消しているので正規化する。 CVector3 moveDir; moveDir.x = cameraX.x * moveDirLocal.x + cameraZ.x * moveDirLocal.z; moveDir.y = 0.0f; //Y軸はいらない。 moveDir.z = cameraX.z * moveDirLocal.x + cameraZ.z * moveDirLocal.z; moveSpeed.x = moveDir.x * MOVE_SPEED; moveSpeed.z = moveDir.z * MOVE_SPEED; //Y方向には重力落下を加える。 const float GRAVITY = -18.8f; moveSpeed.y += GRAVITY * GameTime().GetFrameDeltaTime(); CVector3 addPos = moveSpeed; addPos.Scale(GameTime().GetFrameDeltaTime()); nextPosition.Add(addPos); if (moveDir.LengthSq() > 0.0001f) { rotation.SetRotation(CVector3::Up, atan2f(moveDir.x, moveDir.z)); //走り状態に遷移。 state = enStateRun; } else { //立ち状態。 state = enStateStand; } ShadowMap().SetLightTarget(position); CVector3 lightPos; lightPos.Add(position, toLightPos); ShadowMap().SetLightPosition(lightPos); //コリジョン検出と解決を行う。 CollisionDetectAndResolve(nextPosition); } else if (state == enState_RideOnCar) { ShadowMap().SetLightTarget(g_car->GetPosition()); CVector3 lightPos; lightPos.Add(g_car->GetPosition(), toLightPos); ShadowMap().SetLightPosition(lightPos); if (g_car->GetMoveSpeed().Length() < 0.1f) { //車が停止状態。 if (Pad(0).IsPress(enButtonB)) { //降車。 g_camera->SetCar(NULL); g_car->SetRideOnFlag(false); skinModel.SetShadowReceiverFlag(true); skinModel.SetShadowCasterFlag(true); position = g_car->GetPosition(); state = enStateStand; } } } skinModel.Update(position, rotation, CVector3::One); //ポイントライトの位置を更新。 UpdatePointLightPosition(); //アニメーションコントロール。 AnimationControl(); lastFrameState = state; }