W32 Key Move


上下左右の矢印キーでエネミーを動かします。

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

プログラムの説明

  1. [Windows デスクトップ アプリケーション] はメッセージループで描画する Win32 API に準じるプラットホームです。
    メッセージループで描画すると DirectX と同様に画像のスクロールやアニメーションが可能になります。
    上下左右の矢印キーでエネミーを動かしてみましょう。
    Visual Studio で [C++ Windows デスクトップ] のプロジェクトを作成します。
    プロジェクトの作成は W32 Hello を参照して下さい。
  2. WindowsProject1.cpp の修正です。
    W32 Scroll で使った LoadBMP() 関数を使用します。
    struct で IMG 構造体を定義します。
    XPOS, YPOS; はエネミーを描画する座標です。
    FX, FY はコンピュータの速度が非常に速くなったので、一度に 0.02 ずつ移動計算をする領域です。
    typedef struct
    {
        int     width,height;
        HBITMAP hBmp;
        HDC     hBmpDC;
    }   IMG;
    IMG         img;
    
    int     XPOS, YPOS;      // 描画する座標
    float   FX=0, FY=0;
    
  3. 続いて LoadBMP() 関数をコーディングします。
    szBitmap で指定された画像ファイルをロードして IMG 構造体に設定します。
    //★ BitMap 画像をロードする
    HRESULT  LoadBMP(HWND hWnd, LPCWSTR szBitmap)
    {
        HDC         hdc;
        BITMAP      bmp;
    
        img.hBmp = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0,
            LR_LOADFROMFILE | LR_CREATEDIBSECTION);
        if (img.hBmp == NULL)
        {
            MessageBox(NULL, szBitmap, L"LoadBMP", MB_OK);
            return S_FALSE;
        }
    
        hdc = GetDC(hWnd);
        img.hBmpDC = CreateCompatibleDC(hdc);
        SelectObject(img.hBmpDC, img.hBmp);
        GetObject(img.hBmp, sizeof(BITMAP), &bmp);
        img.width = bmp.bmWidth;
        img.height = bmp.bmHeight;
        ReleaseDC(hWnd, hdc);
        return S_OK;
    }
    
  4. 続いてキーの押し下げを検出する KeyCheck() 関数をコーディングします。
    GetKeyboardState() が現在のキーの状態を取得する低レベル(最速)の関数です。
    FX, FY を一度に 0.02 ずつ移動して、XPOS, YPOS に int に変換して格納(かくのうが文字化け? (^_^;) )します。
    void KeyCheck(HWND hwnd)
    {
        BYTE    KeyBuffer[256];
        BOOL    state;
    
        // キーボードの状態を読み取る
        GetKeyboardState(KeyBuffer);
        if (KeyBuffer[VK_ESCAPE] & 0xf0)            //ESC
        {
            PostMessage(hwnd, WM_CLOSE, 0, 0);     	//WM_CLOSE をポスト
            return;
        }
        if (KeyBuffer[VK_UP] & 0xf0) { FY-= 0.02; InvalidateRect(hwnd, NULL, FALSE); }
        if (KeyBuffer[VK_DOWN] & 0xf0) { FY+= 0.02; InvalidateRect(hwnd, NULL, FALSE); }
        if (KeyBuffer[VK_LEFT] & 0xf0) { FX-= 0.02; InvalidateRect(hwnd, NULL, FALSE); }
        if (KeyBuffer[VK_RIGHT] & 0xf0) { FX+= 0.02; InvalidateRect(hwnd, NULL, FALSE); }
        XPOS = (int)FX;
        YPOS = (int)FY;
    }
    
  5. 速度を重視して、メッセージ ループから直接 KeyCheck() 関数を呼び出します。
    キーを直接調べるときは TranslateMessage(&msg); は不要(ふようが文字化け? (^_^;) )です。
        // メイン メッセージ ループ:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                //TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            KeyCheck(msg.hwnd);
        }
    
  6. WM_CREATE: で "c:\tmp\Enemy.bmp" を入力します。
    事前に c:\tmp にページ先頭の Enemy.bmp を格納しておいて下さい。
        switch (message)
        {
        case WM_CREATE:
            LoadBMP(hWnd, L"c:\\tmp\\Enemy.bmp");
            break;
    
  7. WM_PAINT: で XPOS, YPOS の座標に Enemy.bmp の画像を描画します。
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                // TODO: HDC を使用する描画コードをここに追加してください...
                BitBlt(hdc, XPOS, YPOS, img.width, img.height, img.hBmpDC, 0, 0, SRCCOPY);
                EndPaint(hWnd, &ps);
            }
            break;
    
  8. プログラムを終了する前に IMG 構造体の領域を解放して下さい。
        case WM_DESTROY:
            DeleteObject(img.hBmp);
            DeleteDC(img.hBmpDC);
            PostQuitMessage(0);
            return 0L;
    
  9. x64 または x86 を選んで、右三角矢印(または F5 キー)でコンパイルします。
    プログラムを起動するとエネミーの画像が左上隅に描画されます。
    上下左右の矢印キーを押すとエネミーが移動します。
    メニューから[ファイル][終了する]を選ぶとプログラムが終了します。
    Windows デスクトップ アプリケーションは UWP のように自動的にメニューに登録されることは無いようです。
    プログラムは Win32 API に準じるようです。詳細は[超初心者のプログラム入門(C言語 Windows)]を参照して下さい。

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

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