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;
}
ゴルフボールを更新する手順を次に示します。
ゴルフボールを更新する手順
[←][→]キーを押し下げてゴルフボールの「転がす方向」を設定する
[↑][↓]キーを押し下げてゴルフボールの「転がす力」を設定する
スペースキーを押し下げてゴルフボールを転がす処理を実行する
● ゴルフボールの「位置」「速度」「向き」を設定する
● ゴルフボールを転がす
ゴルフボールを更新する
// 更新する
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のサイトからダウンロードすることができます。
ゴルフボールを転がすプログラムを実行したときのムービーを次に示します。