Sprite で美人のアニメーション


DirectX の LPD3DXSPRITE->Draw で画像を切り分けて、美人の animation を行います。
Window Size を変更しても Sprite Size が変わらないように設定します。

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

プログラムの説明

  1. [ファイル] [新規作成] [プロジェクト]から空のプロジェクト(Spanime)を作成して下さい。
    プロジェクト/既存項目の追加からプログラムファイルとヘッダファイルをプロジェクトに追加して下さい。
    Spanime.cpp は、プログラムの説明を参考にして作成して下さい。
    myd3d.h と myd3d.cpp は Object Class Library から取得して下さい。
    ファイル名 ファイルの説明
    Spanime.cpp 「プログラムの説明」を参考に作成して下さい
    myd3d.h MyD3D Object Class ヘッダファイル
    myd3d.cpp MyD3D Object Class プログラムファイル
  2. #define と #include と Global Area の定義です。
    タイマを使うので mmsystem.h を組み込んで winmm.lib をリンクする必要があるのですが、 これらの処理は MyD3D.h で行っているので、MyD3D.h を include するだけです。
    *myd3d が MyD3D Object Class の定義です。
    g_pSprite が Sprite Object の定義です。
    g_pTexture が Sprite Object で表示するテクスチャです。
    g_bActive はウインドウが Active 状態のフラグです。
    g_D3DPP は Device 設定のパラメータで、Window Size を変更しても Sprite Size が変わらないように設定するときに使用します。
    bijin.jpg がアニメーションに使用する画像で、このページの先頭のように4行4列で構成されています。
    Pos はスプライトを表示する三次元座標です。
        #define     NAME    "DirectX9 Anime"
        #include    "MyD3D.h"
    
        // Global Area
        HINSTANCE               g_hInst     = NULL;
        HWND                    g_hWnd      = NULL;
        MyD3D                   *myd3d      = NULL;     // MyD3D Object Class
        LPDIRECT3DDEVICE9       g_pDEV      = NULL;     // Direct3DDeviceインターフェイス
        LPD3DXSPRITE            g_pSprite   = NULL;     // スプライト
        LPDIRECT3DTEXTURE9      g_pTexture  = NULL;     // スプライトに使うテクスチャ
        D3DPRESENT_PARAMETERS   g_D3DPP;                // D3DDeviceの設定
        bool                    g_bActive   = false;    // アクティブ状態
        bool                    g_bLost     = false;    // デバイスの消失フラグ
        char                    ImgFile[]   = "bijin16.jpg";
        D3DXVECTOR3     Pos = D3DXVECTOR3(30.0f,25.0f,0.0f);  // スプライトを表示する座標
        
  3. InitDXGraphics() では Direct3D device のインターフェースを取得して Sprite を生成します。
    new MyD3D(g_hWnd) で MyD3D Object Class をインスタンス化します。
    InitD3D() で Direct3D のインターフェースを取得します。
    g_D3DPP に Device 設定のパラメータを格納します。
    D3DXCreateSprite() で Sprite を生成します。
    myd3d->LoadTexture() で表示する画像を入力します。
    画像のサイズは 480*480 ですが「2のべき乗」に引き伸ばされて 512*512 で格納されます。
    Draw 関数では Sprite のサイズを 128 で計算していることに注目して下さい。
    サイズを変更されたく無いときは D3DXCreateTextureFromFileEx() でサイズを指定して入力して下さい。
        HRESULT InitDXGraphics(void)
        {   HRESULT  hr;
    
            // Direct3D デバイスの設定
            myd3d= new MyD3D(g_hWnd);
            if (FAILED(myd3d->InitD3D(&g_pDEV)))
            {   MessageBox(NULL,"Init 3DGraphics Error","Error Message", MB_OK);
                return E_FAIL;
            }
            g_D3DPP= myd3d->D3DPPWin;
            // スプライトを生成
            hr = D3DXCreateSprite(g_pDEV, &g_pSprite);
            if (FAILED(hr))
                return DXTRACE_ERR("InitDXGraphics D3DXCreateSprite", hr);
            // g_pTexture にアニメーション画像を入力
            g_pTexture= myd3d->LoadTexture(ImgFile);
            return S_OK;
        }
        
  4. Sprite の描画(アニメーション)の処理です。
    2003 から Begin() と Draw() の仕様が変わっています。
    透明色やアルファブレンドを使わないときは g_pSprite->Begin(0) で始めます。
    美人のアニメーション画像は4行4列の16枚の Sprite で構成されています。
    画像のサイズは 480*480 なのですが「2のべき乗」に引き伸ばされて一枚のサイズは 128*128 で計算します。
    表示する Sprite の番号をタイマを使って n に求めます。
    300 は Sprite を切り替える速度で、小さな値にすると速くなります。
    n を元に表示する Sprite の矩形領域を rec に設定します。
        HRESULT Draw(void)
        {   int     n;
            RECT    rec;
    
            if (!g_pDEV || !g_bActive)  return false;
            n= (timeGetTime()/300)%16;      //時間で画像を切り替える
            rec.top= (n/4)*128;
            rec.left= (n%4)*128;
            rec.bottom= rec.top+128;
            rec.right= rec.left+128;
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(150,150,150),1.0f,0);
            // シーンの描画開始
            if (SUCCEEDED(g_pDEV->BeginScene()))
            {   // シーンの描画
                g_pSprite->Begin(0);
                g_pSprite->Draw(g_pTexture,&rec,NULL,&Pos,0xffffffff);
                g_pSprite->End();
                // シーンの描画終了
                g_pDEV->EndScene();
            }
            // シーンの表示
            return g_pDEV->Present(NULL,NULL,NULL,NULL);
        }
        
  5. g_pSprite->Draw() 関数の説明です。
    LPDIRECT3DTEXTURE9 g_pTexture テクスチャ画像
    CONST RECT &rec Sprite の表示範囲
    CONST D3DXVECTOR3 NULL Sprite の中心点
    CONST D3DXVECTOR3 &Pos Sprite の中心点の表示座標
    D3DCOLOR 0xffffffff ベースの色
  6. CALLBACK 関数です。
    WM_SIZE: でウインドウサイズが変更されたとき、画像のサイズが変わらないようにします。
    変更された幅と高さを g_D3DPP に格納して ChangeWindowSize() を呼び出します。
    escape キーが押されるとプログラムを終了します。
        LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
        {   HRESULT hr = S_OK;
    
            switch(msg)
            {   case WM_ACTIVATE:
                    g_bActive = (LOWORD(wParam) != 0);
                    break;
                case WM_SIZE:
                    if (!g_pDEV || wParam==SIZE_MINIMIZED)    break;
                    g_D3DPP.BackBufferWidth  = LOWORD(lParam);
                    g_D3DPP.BackBufferHeight = HIWORD(lParam);
                    if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED)
                        ChangeWindowSize();
                    break;
                case WM_KEYDOWN:
                    switch(wParam)
                    {   case VK_ESCAPE:
                            PostMessage(hWnd,WM_CLOSE,0,0);
                            break;
                    }
                    break;
                case WM_DESTROY:
                    if (g_pSprite)  g_pSprite->OnLostDevice();
                    CleanupDXGraphics();
                    PostQuitMessage(0);
                    g_hWnd = NULL;
                    return 0;
                }
                return DefWindowProc(hWnd, msg, wParam, lParam);
        }
        
  7. ウインドウ・サイズの変更です。
    この関数を実行するとウインドウサイズが変更されても画像のサイズは変わりません。
        HRESULT ChangeWindowSize(void)
        {   HRESULT hr;
    
            if (g_pSprite)  g_pSprite->OnLostDevice();
            hr = g_pDEV->Reset(&g_D3DPP);
            if (FAILED(hr))
            {
                DestroyWindow(g_hWnd);
                return DXTRACE_ERR("ChangeWindowSize Reset", hr);
            }
            hr = ResetSprite();
            if (FAILED(hr))
            {   DestroyWindow(g_hWnd);
                return DXTRACE_ERR("ChangeWindowSize ResetSprite", hr);
            }
            return hr;
        }
        
  8. Sprite の Reset です。
    ウインドウ・サイズが変更されたときやデバイスが消失したときに呼ばれます。
        HRESULT ResetSprite(void)
        {   HRESULT hr= S_FALSE;
            if (g_pSprite)  hr= g_pSprite->OnResetDevice();
            return hr;
        }
        
  9. DirectX Graphics の終了処理です。
    取得したインターフェースやオブジェクトは必ず開放して下さい。
        bool CleanupDXGraphics(void)
        {
            SAFE_RELEASE(g_pSprite);
            SAFE_RELEASE(g_pTexture);
            SAFE_DELETE(myd3d);
            return true;
        }
        

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

超初心者のプログラム入門(DirectX9 game program)