図0105a
動画は以下になります。
//-------------------------------------------------------------------------------------- /// プレイヤー //-------------------------------------------------------------------------------------- class Player : public GameObject { //中略 //階層化ステートマシーン unique_ptr<LayeredStateMachine<Player>> m_StateMachine; public: //中略 //アクセサ //-------------------------------------------------------------------------------------- /*! @brief ステートマシンを得る @return ステートマシン */ //-------------------------------------------------------------------------------------- unique_ptr<LayeredStateMachine<Player>>& GetStateMachine() { return m_StateMachine; } //初期化 virtual void OnCreate() override; //中略 };
//初期化
void Player::OnCreate() {
//中略
//ステートマシンの構築
m_StateMachine.reset(new LayeredStateMachine<Player>(GetThis<Player>()));
//最初のステートをPlayerDefaultにリセット
m_StateMachine->Reset(PlayerDefaultState::Instance());
}
1、Reset(): スタックをすべてクリアし、Topにステートを設定する 2、Push(): スタックに指定のステートを積む。Topが新しいステートになる 3、Pop(): スタックのTopからステートをなくす。Topの一つ下が新しいTopになる
//-------------------------------------------------------------------------------------- /// コントローラのボタンのハンドラ //-------------------------------------------------------------------------------------- template<typename T> struct InputHandler { void PushHandle(const shared_ptr<T>& Obj) { //コントローラの取得 auto CntlVec = App::GetApp()->GetInputDevice().GetControlerVec(); if (CntlVec[0].bConnected) { //Aボタン if (CntlVec[0].wPressedButtons & XINPUT_GAMEPAD_A) { Obj->OnPushA(); } //Bボタン else if (CntlVec[0].wPressedButtons & XINPUT_GAMEPAD_B) { Obj->OnPushB(); } } } };
//-------------------------------------------------------------------------------------- /// プレイヤー //-------------------------------------------------------------------------------------- class Player : public GameObject { //中略 //入力ハンドラー InputHandler<Player> m_InputHandler; //中略 public: //中略 //Aボタン void OnPushA(); //Bボタン void OnPushB(); };
//Aボタン void Player::OnPushA() { if (GetStateMachine()->GetTopState() == PlayerDefaultState::Instance()) { switch (m_PlayerAction) { case PlayerAction::Jump: GetStateMachine()->Push(PlayerJumpState::Instance()); break; case PlayerAction::Attack: GetStateMachine()->Push(PlayerAttackState::Instance()); break; } } } //Bボタン void Player::OnPushB() { switch (m_PlayerAction) { case PlayerAction::Jump: m_PlayerAction = PlayerAction::Attack; break; case PlayerAction::Attack: m_PlayerAction = PlayerAction::Jump; break; } }
//Aボタンで動作するアクション enum class PlayerAction { Jump, Attack };
void PlayerJumpState::Execute(const shared_ptr<Player>& Obj) {
//ジャンプ中も方向変更可能
auto PtrDefault = Obj->GetBehavior<PlayerBehavior>();
PtrDefault->MovePlayer();
auto PtrJump = Obj->GetBehavior<JumpBehavior>();
if (PtrJump->Execute()) {
Obj->GetStateMachine()->Pop();
}
}
void PlayerAttackState::Execute(const shared_ptr<Player>& Obj) {
//すぐにステートを戻す
Obj->GetStateMachine()->Pop();
}
法線マップ
この画像は各値が法線になってますので、シェーダの描画時に光の向きに合わせて各ピクセル色を調整します。
テクスチャと法線マップ
そうすると、左側にあるボックスのように、テクスチャの模様が法線マップに合わせて、でこぼこしているように表現できます。strTexture = DataDir + L"wall.jpg"; App::GetApp()->RegisterTexture(L"WALL_TX", strTexture); strTexture = DataDir + L"wall_normal.png"; App::GetApp()->RegisterTexture(L"WALL_NORMAL_TX", strTexture);
auto PtrDraw = AddComponent<BcPNTnTStaticDraw>(); PtrDraw->SetMeshResource(L"DEFAULT_PNTnT_CUBE"); PtrDraw->SetTextureResource(L"WALL_TX"); PtrDraw->SetNormalMapTextureResource(L"WALL_NORMAL_TX");
//-------------------------------------------------------------------------------------- /// 位置と法線とタンジェントとテクスチャを持つ入力レイアウトの定義 //-------------------------------------------------------------------------------------- const D3D11_INPUT_ELEMENT_DESC VertexPositionNormalTangentTextureLayout[] = { { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, };
//PNT頂点のCubeを作成 vector<VertexPositionNormalTexture> vertices; vector<uint16_t> indices; MeshUtill::CreateCube(1.0f, vertices, indices);
//タンジェント付きの頂点の配列にコンバート vector<VertexPositionNormalTangentTexture> new_pntnt_vertices; for (size_t i = 0; i < vertices.size(); i++) { //タンジェント付きの頂点の変数 VertexPositionNormalTangentTexture new_pntnt_v; //PNT頂点からコピー new_pntnt_v.position = vertices[i].position; new_pntnt_v.normal = vertices[i].normal; new_pntnt_v.textureCoordinate = vertices[i].textureCoordinate; //とりあえずタンジェントは0初期化 new_pntnt_v.tangent = Vec4(0,0,0,0); //頂点の配列に追加 new_pntnt_vertices.push_back(new_pntnt_v); }
//タンジェント要素(接ベクトル)を法線から計算 MeshUtill::SetNormalTangent(new_pntnt_vertices);
//メッシュ作成
auto PtrNewMesh =
MeshResource::CreateMeshResource(new_pntnt_vertices, indices, false);
//リソース登録 App::GetApp()->RegisterResource(L"MY_CUBE", PtrNewMesh);
vector<VertexPositionNormalTexture> vertices; vector<uint16_t> indices; //PNT頂点のCubeを作成 MeshUtill::CreateCube(1.0f, vertices, indices); //タンジェント付きの頂点の配列にコンバート vector<VertexPositionNormalTangentTexture> new_pntnt_vertices; for (size_t i = 0; i < vertices.size(); i++) { //タンジェント付きの頂点の変数 VertexPositionNormalTangentTexture new_pntnt_v; //PNT頂点からコピー new_pntnt_v.position = vertices[i].position; new_pntnt_v.normal = vertices[i].normal; new_pntnt_v.textureCoordinate = vertices[i].textureCoordinate; //とりあえずタンジェントは0初期化 new_pntnt_v.tangent = Vec4(0,0,0,0); //頂点の配列に追加 new_pntnt_vertices.push_back(new_pntnt_v); } //タンジェント要素(接ベクトル)を法線から計算 MeshUtill::SetNormalTangent(new_pntnt_vertices); //メッシュ作成 auto PtrNewMesh = MeshResource::CreateMeshResource(new_pntnt_vertices, indices, false); //リソース登録 App::GetApp()->RegisterResource(L"MY_CUBE", PtrNewMesh);