DirectX2D Anime Class


DirectX2D の Anime Class で美人のアニメーションを行います。

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

プロジェクトの作成

  1. DirectX2D Image Load では、画像を入力する処理を一個の関数にまとめました。
    今回は IMAGE(画像ファイル)を切り分けて描画する Anime Object Class を作成します。
    Windows8 DirectX では Object Class の様子が C/C++ と違います。
    そこでサンプルプログラムに準じて Anime Class を作成してみました。
  2. 空プロジェクト を参照してベースとなる XAML 無しのプロジェクトを構築して下さい。
    Object Class の説明はC/C++の Windows 8.1 Class を参照して下さい。
  3. Anime.h と Anime.cpp を Content\ のフォルダに格納して、プロジェクトに追加して下さい。
    Anime.h のソースコードです。
    /********************************************/
    /* Anime Class Header(Windows8.1)   前田 稔 */
    /********************************************/
    #include "..\Common\DeviceResources.h"
    #include "..\Common\StepTimer.h"
    #include "..\Common\DirectXHelper.h"
    
    namespace App1
    {
        class Anime
        {
        public:
            Anime(std::shared_ptr<DX::DeviceResources> Resource);
            void CreateDeviceDependentResources();
            void ReleaseDeviceDependentResources();
            void Update(DX::StepTimer const& timer);
            void Render();
            void Render(int wp, int hp);
            void Load(WCHAR *uri, int w, int h);
            void Load(WCHAR *uri);
        private:
            Microsoft::WRL::ComPtr<ID2D1DeviceContext1> m_d2dContext;
            Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
            Microsoft::WRL::ComPtr<ID2D1Bitmap1>  m_bitmapPerspective;
    
            int         m_Num;      //Updateで更新するSpriteの番号
            int         m_Width;    //Spriteの幅
            int         m_Height;   //Spriteの高さ
            int         m_Wnum;     //画像の幅/Spriteの幅
            float       m_fWidth;   //画像の幅
            float       m_fHeight;  //画像の高さ
            D2D1_RECT_F sou;        //送り側矩形
            D2D1_RECT_F dest;       //受取り側矩形
        };
    }
    
  4. Anime.cpp のソースコードです。
    /********************************************/
    /* Anime Object Class(Windows8.1)   前田 稔 */
    /********************************************/
    #include "pch.h"
    #include "Anime.h"
    
    using namespace Microsoft::WRL;
    using namespace Windows::Graphics::Display;
    using namespace App1;
    
    // Constructor
    Anime::Anime(std::shared_ptr<DX::DeviceResources> Resource)
    {
        m_d2dContext = Resource->GetD2DDeviceContext();
        m_wicFactory = Resource->GetWicImagingFactory();
    }
    
    void Anime::Load(WCHAR *uri, int w, int h)
    {
        D2D1_SIZE_U Size;
        m_Width = w;
        m_Height = h;
    
        ComPtr<IWICBitmapDecoder> decoder;
        DX::ThrowIfFailed(
            m_wicFactory->CreateDecoderFromFilename(
            uri,
            nullptr,
            GENERIC_READ,
            WICDecodeMetadataCacheOnDemand,
            &decoder
            )
            );
    
        ComPtr<IWICBitmapFrameDecode> frame;
        DX::ThrowIfFailed(
            decoder->GetFrame(0, &frame)
            );
    
        ComPtr<IWICFormatConverter> converter;
        DX::ThrowIfFailed(
            m_wicFactory->CreateFormatConverter(&converter)
            );
    
        DX::ThrowIfFailed(
            converter->Initialize(
            frame.Get(),
            GUID_WICPixelFormat32bppPBGRA,
            WICBitmapDitherTypeNone,
            nullptr,
            0.0f,
            WICBitmapPaletteTypeCustom
            )
            );
    
        DX::ThrowIfFailed(
            m_d2dContext->CreateBitmapFromWicBitmap(
            converter.Get(),
            nullptr,
            &m_bitmapPerspective
            )
            );
    
        Size = m_bitmapPerspective->GetPixelSize();
        m_Wnum = Size.width / m_Width;
        m_fWidth = (float) Size.width;
        m_fHeight = (float) Size.height;
    }
    
    // w, h が省略されると 32, 32 に設定する
    void Anime::Load(WCHAR *uri)
    {
        Load(uri, 32, 32);
    }
    
    // 汎用性を考えるなら、切り替え速度:2000000やSpriteの枚数:8に考慮が必要
    void Anime::Update(DX::StepTimer const& timer)
    {
        m_Num= (int)(timer.GetTotalTicks()/2000000) % 8;
    }
    
    // 画像全体をテスト描画
    void Anime::Render()
    {
        m_d2dContext->BeginDraw();  
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        m_d2dContext->DrawBitmap(m_bitmapPerspective.Get());
        HRESULT hr = m_d2dContext->EndDraw();
        if (hr != D2DERR_RECREATE_TARGET)
        {   DX::ThrowIfFailed(hr);  }
    }
    
    // Update で更新された m_num の Sprite を wp,hp に描画
    void Anime::Render(int wp, int hp)
    {
        sou.left = (float) ((m_Num%m_Wnum)*m_Width);
        sou.right = sou.left + (float) m_Width;
        sou.top = (float) ((m_Num / m_Wnum)*m_Height);
        sou.bottom = sou.top + (float) m_Height;
        dest.left = (float) wp;
        dest.right = dest.left + (float) m_Width;
        dest.top = (float) hp;
        dest.bottom = dest.top + (float) m_Height;
    
        m_d2dContext->BeginDraw();
        m_d2dContext->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
        m_d2dContext->DrawBitmap(
            m_bitmapPerspective.Get(),
            &dest, 1.0f,
            D2D1_INTERPOLATION_MODE_LINEAR,
            &sou);
        HRESULT hr = m_d2dContext->EndDraw();
        if (hr != D2DERR_RECREATE_TARGET)
        {
            DX::ThrowIfFailed(hr);
        }
    }
    
    void Anime::CreateDeviceDependentResources()
    {
    }
    
    void Anime::ReleaseDeviceDependentResources()
    {
    }
    
  5. プログラムの内容を少しだけ説明しましょう。
    Constructor では DeviceResources を受け取ります。
    Load(WCHAR *uri, int w, int h) メソッドで画像をロードして、画像を切り分ける情報を設定します。
    w,h は Sprite(切り分ける画像)のサイズです。
    Load(WCHAR *uri); メソッド(サイズを省略する)は Sprite のサイズを 32,32 でロードします。
    Render(int wp, int hp); メソッドで m_Num 番目の Sprite を座標 wp,hp に描画します。
    Render(); メソッド(パラメータを省略)は、画像全体のテスト描画に使用します。
    Update() メソッドで Sprite 番号(m_Num)を更新します。
    2000000 で切り替え速度を調整して下さい。
    8 は Sprite の枚数("Bijin.jpg" の場合)です。
    Anime Class に汎用性を持たせるには、画像サイズと Spriteサイズの関係から枚数を計算して下さい。
    また切り替え速度もパラメータで設定できるようにします。
  6. フォルダに画像ファイル("Bijin.jpg")を格納します。
    プロジェクト名を右クリックして、ADD の既存項目から選択すると、Assets/Bijin.jpg が追加されます。
  7. App1Main.h で Anime Class を定義します。
    #include "Content\Anime.h"
    
        std::unique_ptr<Anime> m_Anime;
    
  8. App1Main.cpp の修正です。
    App1Main::App1Main() 関数(Constructor)で、Anime Class を生成します。
    パラメータとして m_deviceResources を渡します。
    m_deviceResources; は App.h で定義されています。
    96,96 は Sprite 一枚分の大きさです。
        m_Anime = std::unique_ptr(new Anime(m_deviceResources));
        m_Anime->Load(L"Bijin.jpg",96,96);
    
    void App1Main::Update() で m_timer をパラメータとして、Anime Class を更新します。
        m_Anime->Update(m_timer);
    
    bool App1Main::Render() からアニメーションを描画します。
    400,200 は描画する座標です。
        m_Anime->Render(400, 200);
    

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