Map Chip で背景を表示

MAP 上にキャラを表示



上の画像のように Map Chip を組み合わせて、大きな背景画像 BG(Back Ground) を表示します。
特に RPG では World Map や Field Map やダンジョンなど多くの場面で BG(背景画像)を使用します。
BG は Sprite と共にゲームプログラムの基本です。
ここでは MyD3D Object Class を使って BG を表示するプログラムを作成します。

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

プログラムの説明

  1. Map Chip は背景を作成するパーツの集まりで、これをタイルのように配置して大きな背景画面を構成します。
    今回使用する Map Chip は、ページ先頭に表示したように「16 dot * 16 dot」の Chip を横に20個、縦に4個並べた画像です。
    MyD3D Object Class には DirectX の SPRITE とは別に、私が作成した Sprite 機能がインプリメントされています。
    これを使えば、簡単に BG を描画することができます。
  2. 宣言と Global Area の定義です。
    *myd3d は MyD3D Object Class の定義です。
    g_D3DPP はウインドウサイズを変更したときに画像が伸縮しないように設定する領域です。
    ImgFile[] が Mapchip 画像ファイルの名前で GIF 画像を使っています。
    DirectX では JPEG が標準でサポートされているのですが、JPEG は透明色には向きません。
    WINW, WINH はウインドウのサイズで、自由にリサイズすることが出来ます。
    XN,YN は背景画像の大きさで、横と縦に並べる Chip の枚数で指定します。(16倍するとピクセルサイズ)
    XP,YP はビット単位に BG をスクロールする値で、矢印キーで操作します。
    MAP[] は BG を構成する Chip の並び情報を定義した配列です。
        /************************************************/
        /*★ MyD3D Object Class  BackGround   前田 稔 ★*/
        /************************************************/
        #define     NAME    "BackGround"
        #include    "MyD3D.h"
    
        // Global Area
        MyD3D                   *myd3d          = NULL;     // MyD3D Object Class
        HWND                    g_hWnd          = NULL;     // Windows Handle
        LPDIRECT3DDEVICE9       g_pDEV          = NULL;     // Direct3DDeviceインターフェイス
        D3DPRESENT_PARAMETERS   g_D3DPP;                    // D3DDeviceの設定
        bool                    g_bActive       = false;    // アクティブ状態
        char                    ImgFile[]       = "chip.gif";
        int                     WINW= 320, WINH=240;
        int                     XN=15, YN=10;               // BGMAP のサイズ(XN*16) (YN*16)
        int                     XP,YP;                      // Bit Scroll
        int                     MAP[15*10]=
        {   56, 57, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 76, 77, 
            76, 77, 49, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 50, 51, 
            48, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 71, 
            48, 35, 2, 2, 2, 2, 2, 2, 2, 2, 54, 55, 2, 2, 12, 
            48, 15, 2, 2, 54, 55, 2, 2, 2, 2, 74, 75, 2, 2, 32, 
            48, 35, 2, 2, 74, 75, 2, 2, 2, 2, 2, 2, 2, 2, 12, 
            48, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 
            48, 15, 2, 2, 2, 2, 2, 2, 2, 52, 53, 2, 2, 2, 32, 
            57, 44, 45, 2, 2, 2, 2, 2, 2, 72, 73, 2, 46, 46, 47, 
            77, 64, 65, 9, 8, 9, 8, 9, 8, 9, 8, 9, 66, 66, 67, 
        };
        
  3. WinMain() は何時もと同じです。
    ウインドウサイズを WINW,WINH に設定していますが、自由にリサイズすることが出来ます。
    InitDXGraphics() で DirectX を初期化します。
    Draw() が BG を描画する関数です。
        //★ WinMain()
        int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
        {   MSG         msg;
                :
            hr = InitDXGraphics();
            if (FAILED(hr))
            {   UnregisterClass(NAME, hInst);
                return FALSE;
            }
                :
            do
            {   if (PeekMessage(&msg,0,0,0,PM_REMOVE))
                {   TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else    Draw();
            } while (msg.message != WM_QUIT);
                :
        
  4. DirectX を初期化する関数です。
    MyD3D Class を生成して DirectX を初期化し、Mapchip 画像をロードします。
    MyD3D Object Class には私が作成した Sprite 機能がインプリメントされています。
    SetSize() でセルのサイズを設定します。
    これでセルの番号を指定して画像を切り出すことが出来るようになります。
        HRESULT  InitDXGraphics(void)
       {
            myd3d= new MyD3D(g_hWnd);
            myd3d->InitD3D(&g_pDEV);
            g_D3DPP= myd3d->D3DPPWin;
            myd3d->LoadImg(ImgFile);
            myd3d->SetSize(16,16);
            return S_OK;
        }
        
  5. プログラムのメインである MAP[] で定義されたセルの並び情報に従って BGMAP を描画する関数です。
    矢印キーで XP,YP を操作して BGMAP をスクロールします。
    xmd,ymd がセル(16*16) のドット単位の端数で、これの処理方法がポイントです。
    MyD3D Object Class を使えば、セルの番号を指定して描画することができます。
    myd3d->Show(hDC,*(MAP+idx),x*16-xmd,y*16-ymd);
    パラメータ 説明
    hDC 描画対象のHDC
    *(MAP+idx) セルの番号
    x*16-xmd 描画するX座標
    y*16-ymd 描画するY座標
        HRESULT Draw(void)
        {   HDC         hDC;
            int         x,y,idx,xmd,ymd;
    
            if (!g_pDEV || !g_bActive)  return FALSE;
            if (GetAsyncKeyState(VK_ESCAPE)<0)      //ESC キー
            {   PostMessage(g_hWnd,WM_CLOSE,0,0);
                return TRUE;
            }
            if (GetAsyncKeyState(VK_UP)<0 && YP>4)      YP-= 4;
            if (GetAsyncKeyState(VK_DOWN)<0)            YP+= 4;
            if (GetAsyncKeyState(VK_LEFT)<0 && XP>4)    XP-= 4;
            if (GetAsyncKeyState(VK_RIGHT)<0)           XP+= 4;
            g_pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(150,150,150),1.0f,0);
            hDC= myd3d->GetBackDC();
            if (hDC==NULL)
            {   MessageBox(NULL,"GetBackBuffer Error","Error Message", MB_OK);
                return FALSE;
            }
            // BackSurface に直接描画
            xmd= XP%16;
            ymd= YP%16;
            for(y=0; y<=WINH/16; y++)
            {   idx= y+YP/16;
                if (idx>=YN)    break;
                for(x=0; x<=WINW/16; x++)
                {   idx= x+(XP/16);
                    if (idx>=XN)    break;
                    idx+= (y+YP/16)*XN;
                    myd3d->Show(hDC,*(MAP+idx),x*16-xmd,y*16-ymd);
                }
            }
            myd3d->ReleaseBackDC(hDC);
            return g_pDEV->Present(NULL, NULL, NULL, NULL);
        }
        
  6. ウインドウ・サイズが変更されたときの処理です。
    DirectX3D ではそのままでは画像サイズを変更すると画像が伸縮します。
    これを防ぐには次のような処理が必要です。
            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;
        
  7. WM_SIZE: から呼ばれる ChangeWindowSize() 関数です。
    変更されたウインドウの幅と高さを WINW,WINH に設定しています。
        // ウインドウ・サイズの変更
        HRESULT ChangeWindowSize(void)
        {   HRESULT hr;
            RECT    Wrc;
    
            hr = g_pDEV->Reset(&g_D3DPP);
            if (FAILED(hr))  return DXTRACE_ERR("ChangeWindowSize Reset", hr);
            hr= S_FALSE;
            if (FAILED(hr))
            {   DestroyWindow(g_hWnd);
                return DXTRACE_ERR("ChangeWindowSize ResetSprite", hr);
            }
            GetWindowRect(g_hWnd,&Wrc);
            WINW= Wrc.right-Wrc.left;
            WINH= Wrc.bottom-Wrc.top;
            return hr;
        }
        

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

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

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

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