3Dのようにスクロールする

VC++ で背景画像の下側(手前側)を拡大して、3Dのようにスクロールします。

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

プロジェクトの設定

  1. IMAGE Object Class と SURFACE32 Object Class を使います。
    Object Class のソースコードは Object Class Library から取得して下さい。
    *Img は、スクロールする画像を格納する IMAGE Object Class の定義です。
    *Surface32 は、画像を変形する SURFACE32 Object Class の定義です。
    File[] は JPEG 画像ファイルの名前で 640 * 480 の画像を使っています。
    g_Pos はスクロールの位置で 「0~479」を繰り返します。
        /***************************************************/
        /*★ 手前を拡大しながらスクロールする    前田 稔 ★*/
        /***************************************************/
        #define     NAME    "3D Scroll"
        #include    <windows.h>
        #include    "Image.h"
        #include    "Surface32.h"
        #define     SAFE_DELETE(p)  { if (p) { delete (p);     (p)=NULL; } }
    
        HWND        g_hWnd;
        IMAGE       *Img= NULL;
        SURFACE32   *Surface= NULL;                 // Surface Object Class
        char        File[]= "c:\\data\\grid.jpg";   // 640*480
        WORD        g_Pos= 0;
        
  2. CALLBACK 関数の WM_CREATE: で IMAGE Class を生成して、背景画像をロードします。
    PathCheck() はカレントディレクトリをチェックして、無ければパスのフォルダーを検索する関数です。
    次に SURFACE32 Object Class を生成します。
    ピクセル単位(DWORD)で処理するので 32 bit DIB を使って下さい。
    サーフェースが作成できたら Img の画像を hWBmpDC に転送します。
        switch(msg)
        {   case WM_CREATE:
                Img= new IMAGE(hWnd);
                if (Img->PathCheck(File)==-1)
                {   MessageBox(NULL,"ファイルが見つかりません",File,MB_OK);
                    PostQuitMessage(0);
                    return 0L;
                }
                Img->LoadFile(File);
                Surface= new SURFACE32(hWnd,Img->Width,Img->Height);
                Img->Show(Surface->hWBmpDC,0,0);
                break;
        
  3. 描画関数 Render() は WinMain() から呼び出しています。
        //★ Windows Main 関数
        int PASCAL  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
        {   MSG         msg;
                    :
                    :
            ZeroMemory(&msg,sizeof(msg));
            while(msg.message!=WM_QUIT)
            {   if (PeekMessage(&msg,NULL,0U,0U,PM_REMOVE))
                {   TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else    Render();
            }
            return msg.wParam;
        }
        
  4. 描画関数 Render() です。
    SURFACE32 Object Class は画像を加工(ブレンド)するために、二枚の Surface を持っています。
        HBITMAP         hBmp;               //加工後の画像の HBITMAP
        HDC             hBmpDC;             //加工後の画像の HDC
        LPBYTE          Data;               //加工後の画像の BITMAP DATA
        HBITMAP         hWBmp;              //元の画像の HBITMAP
        HDC             hWBmpDC;            //元の画像の HDC
        LPBYTE          WData;              //元の画像の BITMAP DATA
        
    WM_CREATE: で元の画像が hWBmpDC に格納されています。
    Surface->Scroll3D() で、元の画像を下側が拡大するように変形して描画します。
        //描画処理
        VOID  Render()
        {   HDC     hDC;
    
            if (Surface==NULL)  return;
            hDC= GetDC(g_hWnd);
            g_Pos= (g_Pos+1)%480;
            Surface->Scroll3D(Surface->Data,Surface->WData,g_Pos,4.0f,1.0f);
            BitBlt(hDC,0,0,Img->Width,Img->Height,Surface->hBmpDC,0,0,SRCCOPY);
            ReleaseDC(g_hWnd,hDC);
        }
        
  5. このプログラムのテーマである Scroll3D() 関数の説明です。
    ピクセル毎に DWORD(32 bit) で処理するので 32 bit DIB を使って下さい。
    32 bit DIB の説明は 画像の fadeout を参照して下さい。
    wdata の画像の下側(手前)を拡大して、3Dのように変形して data に画像を生成します。
        // wdata の画像を手前を拡大して3Dのように変形して data に格納する
        // pos:スクロールのY基点  rate:拡大率  sade:拡大の中心
        HRESULT  SURFACE32::Scroll3D(LPBYTE data, LPBYTE wdata, long pos, float rate, float side)
        {   static  int     dx,dy,xp,yp;
            static  float   width,height,newwx,a;
            DWORD           *pDBits,*pSBits;
    
            // 図形変形処理
            pDBits= (DWORD*)data;
            pSBits= (DWORD*)wdata;
            width = (float)Width;
            height= (float)Height;
            newwx = width/rate;
            for(dy=0; dy<Height; dy++)
            {   yp= (pos+dy)%Height;
                a= (width-newwx) * dy / height + newwx;
                for(dx=0; dx<Width; dx++)
                {   xp= (int)(a * dx / width + (width-a)/side);
                    *(pDBits+dy*Width+dx)= *(pSBits+yp*Width+xp);
                }
            }
            return TRUE;
        }
        
  6. Scroll3D() 関数のパラメータの説明です。
    名前説明
    Scroll3D3Dのように変形するメンバ関数
    data 変形した画像を格納する BITMAP イメージのポインタ
    wdata 元の画像が格納されている BITMAP イメージのポインタ
    pos スクロールの位置(描画を開始するY座標)
    rate 拡大率
    size 拡大するX座標の中心(2.0 で中央)
  7. size の値は指数関数のように効いてきます。

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