W32 Animation

画像を切り分けてアニメーションをします。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. [Windows デスクトップ アプリケーション] はメッセージループで描画する Win32 API に準じるプラットホームです。
    メッセージループで描画すると DirectX と同様に画像のスクロールやアニメーションが可能になります。
    一枚の画像を切り分けてアニメーションしてみましょう。
    Visual Studio で [C++ Windows デスクトップ] のプロジェクトを作成します。
    プロジェクトの作成は W32 Hello を参照して下さい。
  2. 画像を切り分けて描画する Sprite Class をプロジェクトに組み込みます。
    Sprite.h と Sprite.cpp を utf-8 でタイプして[プロジェクト][既存の項目の追加]からプロジェクトに加えます。
  3. Sprite.h のソースコードです。
    //★ Sprite Object Header File  前田 稔
    #include <windows.h>
    class SPRITE
    { protected:
        HWND        hWnd;
        HDC         hMdc;
        WORD        WNum;               //横方向の SPrite 個数
        WORD        HNum;               //縦方向の SPrite 個数
        WORD        SWidth;             //Sprite の幅
        WORD        SHeight;            //Sprite の高さ
        WORD        xp,yp;
    
      public:
        SPRITE(HWND hWnd);              //Constructor
        ~SPRITE();                      //Destructor
        WORD        Width;              //画像の幅
        WORD        Height;             //画像の高さ
        char        szFile[MAX_PATH];   //オープンするファイル名(パス付き)
    
        HRESULT     Load(const wchar_t szBitmap[], WORD WN, WORD HN);
        HRESULT     Show(HDC hdc, WORD n, WORD x, WORD y);
    };
    
  4. Sprite.cpp のソースコードです。
    Load() 関数で一枚の画像をロードして、切り分ける枚数を設定します。
    Show() 関数が切り分けた Sprite を描画する関数です。
    デストラクタで設定された領域を解放して下さい。
    //★ SPRITE Object Class Library  前田 稔
    #include "Sprite.h"
    
    // SPRITE Object Class 関数
    // コンストラクタ(オブジェクトの初期化)
    SPRITE::SPRITE(HWND hwnd)
    {   hWnd= hwnd;
        hMdc= NULL;
        Width=Height=SWidth=SHeight= 0;
        WNum=HNum= 1;
        szFile[0]= '\0';
    }
    
    // デストラクタ(オブジェクトの終了)
    SPRITE::~SPRITE()
    {   if (hMdc)   DeleteDC(hMdc);
        hMdc= NULL;
        Width=Height=SWidth=SHeight= 0;
    }
    
    // Load SPRITE Image
    HRESULT  SPRITE::Load(const wchar_t szBitmap[], WORD WN, WORD HN)
    {   HDC         hdc;
        HBITMAP     hBitmap;
        BITMAP      bmp;
    
        if (hMdc)
        {   DeleteDC(hMdc);
            hMdc= NULL;
            Width=Height= 0;
        }    
        hBitmap= (HBITMAP)LoadImage(NULL,szBitmap,IMAGE_BITMAP,0,0,
                          LR_LOADFROMFILE|LR_CREATEDIBSECTION);
        if (hBitmap==NULL)
        {   MessageBox(hWnd, szBitmap, L"Load BMP Error", MB_OK);
            return  E_FAIL;
        }
    
        WNum= WN;
        HNum= HN;
        hdc= GetDC(hWnd);
        hMdc= CreateCompatibleDC(hdc);
        SelectObject(hMdc, hBitmap);
        GetObject(hBitmap,sizeof(BITMAP),&bmp);
        Width = (WORD)bmp.bmWidth;
        Height = (WORD)bmp.bmHeight;
        SWidth= Width/WNum;
        SHeight= Height/HNum;
        DeleteObject(hBitmap);
        ReleaseDC(hWnd,hdc);
        return  S_OK;
    }
    
    // SPRITE を画面に描画する
    HRESULT  SPRITE::Show(HDC hdc, WORD n, WORD x, WORD y)
    {   if (hMdc==NULL)     return E_FAIL;
        if (n>=WNum*HNum)   return E_FAIL;
        xp= (n%WNum)*SWidth;
        yp= (n/WNum)*SHeight;
        BitBlt(hdc,x,y,SWidth,SHeight,hMdc,xp,yp,SRCCOPY);
        return S_OK;
    }
    
  5. WindowsProject1.cpp の修正です。
    "Sprite.h" を #include して、タイマーを使うので ID_TIMER を定義します。
    SPRITE* Sprite = NULL; で SPRITE Class を定義します。
    no は描画する Sprite の番号です。
    #include "Sprite.h"
    
    #define   MAX_LOADSTRING 100
    #define   SAFE_DELETE(p)  { if (p) { delete (p); (p)=NULL; } }
    #define   ID_TIMER  (WM_APP + 0)
    
    // グローバル変数:
    HINSTANCE hInst;                                // 現在のインターフェイス
    WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
    WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名
    SPRITE* Sprite = NULL;
    int     no = 0;
    
  6. WM_CREATE: で SPRITE を生成して "c:\tmp\bijin16.bmp" を入力します。
    事前に c:\tmp にページ先頭の bijin16.bmp ファイルを格納しておいて下さい。
    4, 4 は横方向と縦方向の分割数です。
    SetTimer() でタイマー割込みを設定して、アニメーションを開始します。
        case WM_CREATE:
            Sprite = new SPRITE(hWnd);
            Sprite->Load(L"c:\\tmp\\bijin16.bmp", 4, 4);
            SetTimer(hWnd, ID_TIMER, 200, NULL);
            break;
    
  7. WM_TIMER: はタイマー割込みの処理です。
    no をインクリメントして InvalidateRect() でウインドウを再描画します。
        case WM_TIMER:
            no = (no + 1) % 16;
            InvalidateRect(hWnd, NULL, FALSE);
            break;
    
  8. WM_PAINT: で切り分けた no 番目の画像を描画します。
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                // TODO: HDC を使用する描画コードをここに追加してください...
                Sprite->Show(hdc, no, 0, 0);
                EndPaint(hWnd, &ps);
            }
            break;
    
  9. プログラムを終了する前にタイマーを止めて Sprite の領域を解放して下さい。
        case WM_DESTROY:
            KillTimer(hWnd, ID_TIMER);
            SAFE_DELETE(Sprite);
            PostQuitMessage(0);
            break;
    
  10. x64 または x86 を選んで、右三角矢印(または F5 キー)でコンパイルします。
    プログラムを起動すると美人の顔のアニメーションが描画されます。
    メニューから[ファイル][終了する]を選ぶとプログラムが終了します。
    Windows デスクトップ アプリケーションは UWP のように自動的にメニューに登録されることは無いようです。
    プログラムは Win32 API に準じるようです。詳細は[超初心者のプログラム入門(C言語 Windows)]を参照して下さい。

超初心者のプログラム入門(C/C++)

超初心者のプログラム入門(C言語 Windows)