Win10 KeyRot

Windows10 Direct3D でモデルを Key で回転します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. 一般的なキー入力は、タイプされたキーがキーボードバッファにスタックされて、スタックから一文字ずつ取り出します。
    それに対してゲームプログラムでは「今キーが押されている」ことを検知することが必要です。
    今キーが押されていることは、ウインドウハンドル(m_window)を使って GetAsyncKeyState() で調べます。
    例えば左矢印キー(Left)の検出は次のようになります。
        Windows::UI::Core::CoreVirtualKeyStates KeyState;
        KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Left);
        if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
        {   左矢印キーが押されている  }
    
  2. ウインドウハンドルは App.cpp の SetWindow() 関数で渡されるのですが、キーを調べるのは Sample3DSceneRenderer の Update() 関数です。
    そこで各クラスの Constructor を通じてハンドルをリレーします。
          Class App ⇒ Class App1Main ⇒ Class Sample3DSceneRenderer
    
  3. Win10 Template を参照して DirectX 11 アプリ(ユニバーサル Windows)を作成して下さい。
    カラーキューブが回転しながら描画されます。
    プロジェクトの名前は App1 になっています。
  4. App.h にウインドウハンドルを保存する領域を定義して、App.cpp の SetWindow() 関数で保存して下さい。
    protected:
        Windows::UI::Core::CoreWindow^ m_window;
    
    void App::SetWindow(CoreWindow^ window)
    {   ・・・
        m_window = window;
    }
    
  5. App.cpp の Load() 関数で App1Main を生成するときに m_window を追加します。
    void App::Load(Platform::String^ entryPoint)
    {   if (m_main == nullptr)
        {   m_main = std::unique_ptr<App1Main>(new App1Main(m_deviceResources, m_window));
        }
    }
    
  6. m_window の追加に伴い App1Main.h の Constructor の定義も修正して下さい。
    またウインドウハンドルを保存する領域も定義して下さい。
    App1Main.cpp の Constructor でウインドウハンドルを保存します。
    App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources, Windows::UI::Core::CoreWindow^ window);
    
        Windows::UI::Core::CoreWindow^ m_window;
    
    App1Main::App1Main(const std::shared_ptr<DX::DeviceResources>& deviceResources, Windows::UI::Core::CoreWindow^ window):
        m_deviceResources(deviceResources),
        m_window(window)
    {  }
    
  7. App1Main.cpp の Constructor で Sample3DSceneRenderer を生成するときに m_window を追加します。
        // TODO: これをアプリのコンテンツの初期化で置き換えます。
        m_sceneRenderer = std::unique_ptr<Sample3DSceneRenderer>
            (new Sample3DSceneRenderer(m_deviceResources, m_window));
    
  8. m_window の追加に伴い Sample3DSceneRenderer.h の Constructor の定義も修正して下さい。
    またウインドウハンドルを保存する領域も定義して下さい。
    Sample3DSceneRenderer.cpp の Constructor でウインドウハンドルを保存します。
    これで Sample3DSceneRenderer でキーを調べることが出来るようになります。
        Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources, Windows::UI::Core::CoreWindow^ window);
        Windows::UI::Core::CoreWindow^ window);
    
    Sample3DSceneRenderer::Sample3DSceneRenderer(const std::shared_ptr<DX::DeviceResources>& deviceResources,
                Windows::UI::Core::CoreWindow^ window) :
        m_loadingComplete(false),
        m_degreesPerSecond(45),
        m_indexCount(0),
        m_tracking(false),
        m_deviceResources(deviceResources),
        m_window(window)
    {  }
    
  9. Sample3DSceneRenderer.cpp の Update() 関数で今キーが押されているかを調べます。
    Sample3DSceneRenderer.h に回転情報を格納する RotY を定義して下さい。
        float   RotY = 0;
    
    void Sample3DSceneRenderer::Update(DX::StepTimer const& timer)
    {
        if (!m_tracking)
        {
            Windows::UI::Core::CoreVirtualKeyStates KeyState;
            KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Left);
            if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
            {   RotY -= 0.1f;
                if (RotY<XM_2PI)    RotY += XM_2PI;
            }
            KeyState = m_window->GetAsyncKeyState(Windows::System::VirtualKey::Right);
            if (bool(KeyState & Windows::UI::Core::CoreVirtualKeyStates::Down))
            {   RotY += 0.1f;
                if (RotY>XM_2PI)    RotY -= XM_2PI;
            }
            Rotate(RotY);
        }
    }
    
  10. Rotate() 関数でモデルを回転して Render() 関数で描画するのですが、修正する必要はありません。
    プログラムを実行するとモデルが自動回転しなくなり、「左矢印キー」または「右矢印キー」を押すとモデルが回転します。
    今回はY軸を中心に回転するだけですが、X軸の回転も追加してみて下さい。
  11. Constructor を通じてハンドルをリレーするよりも直接コピーして渡す方が解りやすそうなので X2017 KeyRot を作成してみました。
    モデルの回転は Win10 Rotate または Win10 MouseRot を参照して下さい。
    OnKeyDown の簡単なプロジェクトは[超初心者のプログラム入門(C/C++)]から[VC-2017 Key Count]を参照して下さい。
    OnKeyDown, OnKeyUp で回転するプロジェクトは Win10 Model & Camera を参照して下さい。

【NOTE】

[DirectX 11 および XAML アプリ(ユニバーサル Windows)]では、次のコードでウインドウのハンドルを取得できました。
    CoreWindow^ window = Window::Current->CoreWindow;

所が[DirectX 11 アプリ(ユニバーサル Windows)]では、コンパイルエラーが表示されます。
エラーは Windows::UI::Xaml; を追加すると消えたのですが、XAML を使わないと設定されないらしく、実行すると nullptr でこけます。 (^_^;)
using namespace Windows::UI::Xaml;
 
    CoreWindow^ window = Window::Current->CoreWindow;

そこで今回は SetWindow() 関数で取得したハンドルをリレーして使っています。
ハンドルをリレーするのはちょっと難しそうなので DirectX 2017 KeyRot では Class App(window_1) から Class App1Main(window_2) を経由して Class Sample3DSceneRenderer(m_window) にハンドルをコピーする方法でプログプログラムしています。

超初心者のプログラム入門(DirectX Store)