BG の上でキャラクタが動く

BackBuffer を使って、BG を背景にしてキャラクタが動き回るプログラムを作成します。

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

プログラムの説明

  1. BG を背景にして、キャラクタが動き回るプログラムを作成して下さい。
    BG の描画は Map Chip で背景を表示 を参照して下さい。
    キャラクタの描画は キーの操作でキャラクタを動かす を参照して下さい。
    BG とキャラクタを組み合わせると、キャラクタが移動する度に画面がチラツキます。
    そこで BackBuffer を使って、滑らかに BG 上でキャラクタが動き回るプログラムを作成します。
    BackBuffer の説明は 「ちらつき」を抑えてスクロール を参照して下さい。
  2. Main() プログラムです。
    私有ライブラリ(My.lib)に登録している BACKBUF Class と SPRITE Class を使うので my.lib をリンクしています。
    My.h は Bg.h の中で #include しています。
    BACKBUF *Back が BACKBUF Object Class の定義です。
    BG *Bg が BG Object Class の定義です。
    SPRITE *Char がキャラクタを表示する SPRITE Object Class の定義です。
    g_xp, g_yp がキャラクタを表示する座標です。
    g_n はキャラクタの進行方向を格納する領域です。
    g_chg は二枚の画像を切り替えるフラグです。
        #include    "Bg.h"
        #pragma     once
        #pragma     comment(lib,"my.lib")
        #define     ID_TIMER    (WM_APP + 0)
    
        BACKBUF     *Back= NULL;        //Back Buffer Object
        BG          *Bg= NULL;          //Back Ground Object
        SPRITE      *Char= NULL;        //Charcter Object
        long        g_xp, g_yp;         //キャラクタの座標
        WORD        g_n= 0;             //進行方向(0 ~ 3)
        WORD        g_chg= 0;           //画像切り替えフラグ
        
  3. WM_CREATE: で Object Class をインスタンス化して画像を入力します。
    タイマを起動してキーの押し下げを検出するタイミングを設定します。
            case WM_CREATE:
                Back= new BACKBUF(hWnd);
                Bg= new BG(hWnd);
                Bg->Mapchip("chip.bmp");
                Bg->SetMapTable("bgmap.txt",50,40,50,40);
                Char= new SPRITE(hWnd);
                Char->Load("chr17.bmp",1,8);
                g_xp=g_yp= 300;
                SetTimer(hWnd,ID_TIMER,100,NULL);
                break;
        
  4. WM_TIMER: では進行方向を決めればタイマ割り込みで自動的にキャラクタが進むようにしています。
    キーが操作されたときは進行方向を g_n に設定します。
    g_chg^=1; で交互に「0と1」を切り替えます。
    WM_PAINT: を呼ばずに、ここから Render() 関数で直接描画します。
            case WM_TIMER:
                if (GetAsyncKeyState(VK_ESCAPE)<0)
                {   PostMessage(hWnd,WM_CLOSE,0,0);   return 0L;  }
                if (GetAsyncKeyState(VK_UP)<0)        g_n= 0;
                if (GetAsyncKeyState(VK_RIGHT)<0)     g_n= 1;
                if (GetAsyncKeyState(VK_DOWN)<0)      g_n= 2;
                if (GetAsyncKeyState(VK_LEFT)<0)      g_n= 3;
                switch(g_n)
                {   case 0: g_yp-= 2;  break;
                    case 1: g_xp+= 2;  break;
                    case 2: g_yp+= 2;  break;
                    case 3: g_xp-= 2;  break;
                }
                g_chg^= 1;
                Render();
                break;
        
  5. WM_SIZE: でウインドウサイズが変更されたときに Resize() 関数を呼んで下さい。
    WM_CLOSE: でタイマを停止して、Object を開放して下さい。
            case WM_SIZE:
                Back->Resize();
                return 0L;
            case WM_CLOSE:
                KillTimer(hWnd,ID_TIMER);
                SAFE_DELETE(Back);
                SAFE_DELETE(Bg);
                SAFE_DELETE(Char);
                DestroyWindow(hWnd);
                break;
        
  6. WM_TIMER: から呼ばれる Render() 関数です。
    BackBuffer を LTGRAY_BRUSH でクリアして、BG とキャラクタを描画します。
    Blt() 関数で BackBuffer から FrontBuffer に一挙に転送します。
        VOID  Render()
        {   Back->Clear((HBRUSH)GetStockObject(LTGRAY_BRUSH));
            Bg->View(Back->hBackDC);
            Char->Show(Back->hBackDC,g_n*2+g_chg,g_xp,g_yp);
            Back->Blt();
        }
        

Object Class

  1. BG Object Class のヘッダファイル bg.h です。
    My.lib に登録している SPRITE Object Class と TXTBIN Object Class を継承するので my.h を取り込んでいます。
    View() メソッドで BG を描画するのですが、BackBuffer の HDC に描画するメソッドが追加されています。
    xpos, ypos は DOT 単位のオフセットで、ドット単位でスクロールするときのメソッドです。
    BG Object Class の説明は Map Chip で背景を表示 を参照して下さい。
        //★ Back Ground Object Class Header File  前田 稔
        #include <My.h>
    
        class BG : public SPRITE, public TXT2BIN
        { protected:
            int         XN;             //BG Size 横(XN*16)
            int         YN;             //BG Size 縦(YN*16)
            int         XDN;            //Window 横(XDN*16)
            int         YDN;            //Window 縦(YDN*16)
    
          public:
            int         *MAP;           //BG Map Table
            BG(HWND hWnd);              //Constructor
            ~BG();                      //Destructor
            HRESULT     Mapchip(LPSTR szBitmap);
            HRESULT     SetMapTable(LPSTR szMaptxt, int xn, int yn, int xdn, int ydn);
            HRESULT     View();
            HRESULT     View(HDC hdc);
            HRESULT     View(long xpos, long ypos);
            HRESULT     View(HDC hdc, long xpos, long ypos);
        };
        
  2. My.lib に登録されている BackBuffer Object Class のヘッダファイル BackBuf.h です。
    BackBuffer の説明は 描画の「ちらつき」を抑える を参照して下さい。
        //★ Back Buffer Object Class Header   前田 稔 ★*/
        class BACKBUF
        { protected:
            HWND        hWnd;
            HBITMAP     hBackBitmap;        //Back Buffer HBitMap
            RECT        RC;                 //現在の Windows Rect
    
          public:
            HDC         hBackDC;            //Back Buffer DC
            long        Width;              //Back Buffer の幅
            long        Height;             //Back Buffer の高さ
    
            BACKBUF(HWND hwnd);             //Constructor
            ~BACKBUF();                     //Destructor
            void        Clear(HBRUSH brush);
            void        Blt();
            void        Resize();
        };
        
  3. My.lib に登録されている TXT2BIN Object Class のヘッダファイル Txt2Bin.h です。
    TXT2BIN Class の説明は シップの動きを Text File で制御する を参照して下さい。
        //★ Text Data(BYTE) To Binary Data(int)   前田 稔 ★
        class TXT2BIN
        { protected:
            int         Repeat(int tbl[], BYTE *pos, int value, int sw, int count);
    
          public:
            TXT2BIN();                      //Constructor
            virtual ~TXT2BIN();             //Destructor
            BYTE*       ConvtBin(int tbl[], int n, BYTE *buf);
            HRESULT     SetTable(LPSTR szTxt, int tbl[], int n);
        };
        
  4. My.lib に登録されている SPRITE の元になった CARD Object Class のヘッダファイル Card.h です。
    CARD Object Class をベースにメンバ関数を追加して、使いやすい SPRITE Class を作成して下さい。
    CARD Class の説明は カードイメージを入力して、一枚のカードを表示する を参照して下さい。
        //★ Card Object Header File   前田 稔 ★
        class CARD
        { protected:
            HWND        hWnd;
            HBITMAP     hBmp;               //画像の HBITMAP
            HDC         hBmpDC;             //画像の HDC
            long        WNum;               //横方向の Card 枚数
            long        HNum;               //縦方向の Card 枚数
            long        SWidth;             //CARD の幅
            long        SHeight;            //CARD の高さ
            long        xp,yp;
    
          public:
            CARD(HWND hWnd);                //Constructor
            ~CARD();                        //Destructor
            long        Width;              //画像の幅
            long        Height;             //画像の高さ
            char        szFile[MAX_PATH];   // オープンするファイル名(パス付き)
    
            HRESULT     Load(LPSTR szBitmap, long WN, long HN);
            HRESULT     Show();
            HRESULT     Show(long n,long x,long y,long w,long h,long xoff=0,long yoff=0);
            HRESULT     Show(long n,long x,long y)
                        {  return Show(n,x,y,SWidth,SHeight);  }
            HRESULT     Show(HDC hdc, long n, long x, long y);
            HRESULT     SetNum(long WN, long HN);
            HRESULT     SetSize(long WSIZ, long HSIZ);
        };
        

【演習】

  1. 今まで習った Back Ground Object Class のまとめです。
    次の Object Class を作成してプログラムを完成させて下さい。
    BG(BackGround) Object Class
    BackBuffer Object Class
    TXT2BIN Object Class
    Sprite(CARD) Object Class
  2. キャラクタの動きに合わせて BG をスクロールして下さい。
    BG のスクロールは、次の二通りが基本です。
    1. 現在表示されている背景上ではキャラクタだけを動かし、画面の端にきたときに背景をスクロールする。
    2. キャラクタを常に画面中央に表示するように背景をスクロールする。
      背景がスクロールできなくなったらキャラクタを移動する。

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

前田稔(Maeda Minoru)の超初心者の C++/CLI