見出し画像

DirectX ボールを転がす2

「DirectX ボールを転がす1」でGolfBallクラスを作成し、Golfクラスの概要を解説をしました。本稿ではGolfBallクラスのインスタンスを生成し、転がす方向と力を設定してゴルフボールを転がしてみましょう。

GraphSceneクラスでヘッダファイルをインクルードする

初めに、GraphSceneクラスのヘッダーファイル(GraphScene.h)にGolfBallクラスのヘッダファイル(GolfBall.h)をインクルードします。

#include "GolfBall.h"


GraphSceneクラスでゴルフボールに関連するメンバー変数を宣言する

GraphSceneクラスに、「ゴルフボールのモデルデータ」「ゴルフボールのインスタンスへのポインタ」、ゴルフボールの「転がす角度」「転がす力」を示すメンバー変数を宣言します。メンバー変数はすべて非公開にします。

メンバー変数

  • 開始位置 const DirectX::SimpleMath::Vector2 START_POSITION = DirectX::SimpleMath::Vector2(-80.0f, 0.0f)


メンバー変数

  • ゴルフボールのモデル std::unique_ptr<Model> m_golfBallModel

  • ゴルフボールへのポインタ std::unique_ptr<GolfBall> m_golfBall

  • ロールアングル    float m_rollAngle

  • ロールパワー     float m_rollForce

#pragma once
#ifndef GRAPH_SCENE_DEFINED
#define GRAPH_SCENE_DEFINED
#include "DeviceResources.h"
#include "ArcBall.h"
#include "Game.h"
#include "GolfBall.h"

class Game;

class GraphScene
{
public:
   // 開始位置
   const DirectX::SimpleMath::Vector2 START_POSITION = DirectX::SimpleMath::Vector2(-80.0f, 0.0f);

private:	
   // ゴルフボールのモデル
   std::unique_ptr<DirectX::Model> m_golfBallModel;
   // ゴルフボール
   std::unique_ptr<GolfBall> m_golfBall;
   // ロールアングル
   float m_rollAngle;
   // ロールフォース
   float m_rollForce;
};

#endif		// GRAPH_SCENE_DEFINED


ゴルフボールを初期化する

GraphSceneクラスのコンストラクタでは、メンバー変数の初期化を行います。GraphSceneクラスのInitialize関数では、コンテンツパイプラインで変換されたCMO形式ゴルフボールのモデルをロードします。モデルのロードはGolfBallクラスのInitialize関数で実施することが考えられますが、複数のゴルフボールを生成する場合、複数回、Initialize関数が呼ばれて複数回のモデルのロードが発生しますので、モデルのロードは一度だけ実行するようにします。
次に、GolfBallクラスのインスタンスを生成します。クラスのインスタンスを生成する場合、予めGolfBallクラスのユニークポインタ宣言し、make_unique関数でGolfBallクラスのインスタンスを代入します。

ゴルフボールのモデルをロードする
m_golfBallModel = DirectX::Model::CreateFromCMO(m_device, L"resources\cmo\GolfBall.cmo", *m_graphics->GetFX());

GolfBallクラスのインスタンスを生成する
m_golfBall = std::make_unique<GolfBall>(m_golfBallModel.get());

// 初期化する
void GraphScene::Initialize()
{ 
   // クォータニオンカメラ回転を初期化する
   m_cameraRotation.CreateFromYawPitchRoll(DirectX::SimpleMath::Vector3(0.0f, 1.0f, 0.0f));
   // ゴルフボールのモデルをロードする
   // CMO形式のゴルフボールモデルをロードする
   m_golfBallModel = DirectX::Model::CreateFromCMO(m_device, L"resources\\cmo\\GolfBall.cmo", *m_graphics->GetFX());
   // GolfBallクラスのインスタンスを生成する
   m_golfBall = std::make_unique<GolfBall>(m_golfBallModel.get());
}


ゴルフボールを更新する

ゴルフボールの更新はUpdate関数で行います。Update関数では、矢印キーを操作してゴルフボールを転がす向きと力を設定します。ゴルフボールを転がすには、GolfBallクラスのRoll関数を呼び出します。

ゴルフボールを転がす
GolfBallクラスのRoll関数にゴルフボールを転がす向きと力を渡してゴルフボールを転がします。
m_golfBall->Roll(direction, m_rollForce)

// ゴルフボールを転がす
void GolfBall::Roll(const DirectX::SimpleMath::Vector2& direction, const float& force )
{
   using namespace DirectX::SimpleMath;
   // ゴルフボールが転がる方向ベクトルを正規化する
   Vector2 kickDirection = Normalize(direction);
   // 運動方程式から速度を計算する
   m_velocity = kickDirection * force / m_mass;
}

ゴルフボールを更新する手順を次に示します。

ゴルフボールを更新する手順

  1. [←][→]キーを押し下げてゴルフボールの「転がす方向」を設定する

  2. [↑][↓]キーを押し下げてゴルフボールの「転がす力」を設定する

  3. スペースキーを押し下げてゴルフボールを転がす処理を実行する

  4.  ●  ゴルフボールの「位置」「速度」「向き」を設定する

  5.  ●  ゴルフボールを転がす

  6. ゴルフボールを更新する

// 更新する
void GraphScene::Update(const DX::StepTimer& timer)
{
   using namespace DirectX::SimpleMath;
   ...

   // [←][→]キーでゴルフボールの転がす方向を変える
   if (m_keyboardState.Left && m_keyboardState.LeftControl)
      m_rollAngle += 1.0f;
   if (m_keyboardState.Right && m_keyboardState.LeftControl)
      m_rollAngle -= 1.0f;

   // [↑][↓]キーでゴルフボールの転がす力を変える
   if (m_keyboardState.Up && m_keyboardState.LeftControl)
      m_rollPower += 0.1f;
   if (m_keyboardState.Down && m_keyboardState.LeftControl)
      m_rollPower -= 0.1f;

   // [Space]キーでゴルフボールを転がす
   if (m_game->GetKeyboardTracker().IsKeyPressed(DirectX::Keyboard::Space))
   {
      // ゴルフを転がす方向を設定する
      Vector2 direction(1.0f, 0.0f);
      // 回転行列を生成する
      Matrix rotationMatrix = Matrix::CreateRotationZ(DirectX::XMConvertToRadians(m_rollAngle));
      // 回転後の向きを計算する
      direction = Vector2::Transform(direction, rotationMatrix);
      // ゴルフボールを転がす
      m_golfBall->Roll(direction, m_rollPower);
   }
   // ゴルフボールを更新する
   m_golfBall->Update(elapsedTime);
   ...

}


ゴルフボールを描画する

GraphSceneクラスのRender関数を使用してゴルフボールを描画します。Render関数では、次の手順を実行します。

ゴルフボールを描画する手順

  • グリッドを描画する

  • ゴルフボールを描画する(DrawBall関数)

  • ゴルフボールを転がす方向(矢印)を描画する(DrawRollDirection関数)

  • 情報を描画する(DrawInfof関数)

// 描画する
void GraphScene::Render()
{
   using namespace DirectX::SimpleMath;

   const DirectX::XMVECTORF32 xaxis = { 100.f, 0.0f, 0.0f };
   const DirectX::XMVECTORF32 yaxis = { 0.0f, 0.0f, 100.f };

   // グリッドを描画する
   DrawGrid(xaxis, yaxis, DirectX::g_XMZero, 10, 10, DirectX::Colors::DarkGray);
   // ゴルフボールを描画する
   DrawBall();
   // ゴルフボールを転がす方向を描画する
   DrawRollDirection();
   // 情報を表示する
   DrawInfo();
}


GolfBallクラスのRender関数を呼び出す

GraphSceneクラスのDrawBall関数からGolfBallクラスのインスタンスを通じてGolfBallクラスのRender関数を呼び出します。

// ゴルフボールを描画する
void GraphScene::DrawBall()
{
   // ゴルフボールを描画する
   m_golfBall->Render();
}


ゴルフボールを転がす方向を表す矢印を描画する

ゴルフボールが静止した場合、ゴルフボールを初期位置に設定し、ゴルフボールの速度を初期化します。その後、ゴルフゴールを転がす初期方向と転がす力を表す矢印を描画します。

  • ゴルフボールの位置と速度を初期化する

  • ゴルフボールを転がす方向と力を設定し、矢印を描画する

// ボールを転がす方向を描画する
void GraphScene::DrawRollDirection()
{
   using namespace DirectX::SimpleMath;

   // ゴルフボールが停止した場合
   if (m_golfBall->GetVelocity().Length() < 0.01f )
   {
      // ゴルフボールの初期位置を設定する
      m_golfBall->SetPosition(START_POSITION);
      // 速度を初期化する
      m_golfBall->SetVelocity(Vector2::Zero);
      // ゴルフボールを転がす方向を設定する
      Vector2 angle(1.0f, 0.0f);
      // 回転行列を生成する
      Matrix rotationMatrix = Matrix::CreateRotationZ(DirectX::XMConvertToRadians(m_rollAngle));
      //  ゴルフボールを転がす方向を計算する
      angle = Vector2::Transform(angle, rotationMatrix);
      // 描画プリミティブを開始する
      m_graphics->DrawPrimitiveBegin(m_graphics->GetViewMatrix(), m_graphics->GetProjectionMatrix());
      // ゴルフボールを転がす方向を表す矢印を描画する
      m_graphics->DrawVector(m_golfBall->GetPosition(), angle * m_rollPower * 10.0f);
      // 描画プリミティブを終了する
      m_graphics->DrawPrimitiveEnd();
   }
}


情報を描画する

GraphSceneクラスのDrawInfo関数はカメラとゴルフボールの情報を画面に描画します。

  • カメラの位置

  • カメラの回転角

  • ゴルフボールの位置

  • ゴルフボールの速度

// 情報を表示する
void GraphScene::DrawInfo()
{
   wchar_t stringBuffer[128];
   // SpriteString2Dを宣言する
   SpriteString2D spriteString2D;

   // カメラの位置を書式化する
   swprintf(stringBuffer, sizeof(stringBuffer) / sizeof(wchar_t), L"Camera position: (%6.1f, %6.1f, %6.1f)", 
      m_cameraPosition.x, m_cameraPosition.y, m_cameraPosition.z);
      spriteString2D.AddString(stringBuffer, DirectX::SimpleMath::Vector2(0.0f, 0.0f));
   // カメラの回転角を書式化する
   swprintf(stringBuffer, sizeof(stringBuffer) / sizeof(wchar_t), L"Camera rotation: (%6.1f, %6.1f, %6.1f), %6.1f)",
      m_cameraRotation.x, m_cameraRotation.y, m_cameraRotation.z, m_cameraRotation.w);
      spriteString2D.AddString(stringBuffer, DirectX::SimpleMath::Vector2(0.0f, 28.0f));
   // ゴルフボールの位置を書式化する
   swprintf(stringBuffer, sizeof(stringBuffer) / sizeof(wchar_t), L"GolfBall position: (%6.1f, %6.1f)",
      m_golfBall->GetPosition().x, m_golfBall->GetPosition().y);
      spriteString2D.AddString(stringBuffer, DirectX::SimpleMath::Vector2(0.0f, 56.0f));
   // ゴルフボールの速度を書式化する
   swprintf(stringBuffer, sizeof(stringBuffer) / sizeof(wchar_t), L"GolfBall velocity: (%6.1f, %6.1f)",
      m_golfBall->GetVelocity().x, m_golfBall->GetVelocity().y);
      spriteString2D.AddString(stringBuffer, DirectX::SimpleMath::Vector2(0.0f, 84.0f));
      // すべての情報を描画する
      spriteString2D.Render();
}


これまでのところでゴルフボールを転がす処理を実装することができました。プロジェクトはGithubのサイトからダウンロードすることができます。

ゴルフボールを転がすプログラムを実行したときのムービーを次に示します。



この記事が気に入ったらサポートをしてみませんか?