MapChip でキャラクタを制御

MapChip に「通れる、通れない」を設定してキャラクタを制御します。
モニタの解像度(ウインドウサイズ)を設定して Full Screen Mode で描画します。

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

プログラムの説明

  1. Windows Program の実行環境は、コンシューマゲームのように統一されていません。
    特にモニタの解像度(ウインドウサイズ)は重要で、これがばらばらではゲームに支障をきたします。
    そこでゲームプログラムでは、解像度(ウインドウサイズ)を強制的に設定する方法が良く使われます。
    またモニタをゲームプログラムで占有する Full Screen Mode でプレイする方法も常識です。
  2. new BACKBUF(hWnd) で Object Class をインスタンス化します。
    Back->SetMode(800,600,32) で解像度を指定して Full Screen Mode に設定します。
            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;
                Back->SetMode(WIDTH,HEIGHT,32);
                SetTimer(hWnd,ID_TIMER,100,NULL);
                break;
        
  3. BG(Back Ground)で作成した画像を背景に、セルの属性を利用してキャラクタを動かします。
    RPGゲームでは、マップチップ(セルを構成する画像)に属性を待たせて、キャラクタを制御します。
    今回はキャラクタが「通過できるか(1)、できないか(0)」だけですが、実際のゲームでは、様々な条件が考えられます。
    例えば、次のような条件です。
  4. 属性はマップチップに格納されているセルに対応して与えられ、同じ画像でも属性が違えば別のセルとして扱います。
    このプログラムで使用したマップチップの画像は 16*16 ピクセルで、4行20列で構成されています。
    マップチップに属性を設定する Att[] の定義です。画像と比べてみて下さい。

        BYTE        Att[80]=
        {  1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
           1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
           0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        };
        
  5. BG Object Class にキャラクタが置かれている座標のマップチップ番号を返すメンバ関数を追加します。
    キャラクタ画像を表示する座標は「左上」なので、渡すときに xp,yp を補正して下さい。
        // MapChip の番号を返す
        int  BG::Chip(int xp, int yp)
        {   int     x,y,off;
            x= xp>>4;
            y= yp>>4;
            off= y*XN+x;
            return *(MAP+off);
        }
        
  6. キャラクタの移動を設定する関数です。
    キャラクタのサイズは 32*32 なので、判定の基点を中央の足元に補正しています。
        //キャラクタの移動
        void  move()
        {   int     xp,yp;
            int     ChipNo;
    
            yp= g_yp;
            xp= g_xp;
            switch(g_n)
            {   case 0: yp-= 2;  break;
                case 1: xp+= 2;  break;
                case 2: yp+= 2;  break;
                case 3: xp-= 2;  break;
            }
            if (yp<0)   yp= 0;
            if (xp<0)   xp= 0;
            ChipNo= Bg->Chip(xp+15,yp+25);
            if (Att[ChipNo]==1)
            {   g_yp= yp;
                g_xp= xp;
            }
        }
        
  7. 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;
                move();
                g_chg^= 1;
                Render();
                break;
        
  8. マウスが左クリックされた座標にキャラクタを移動するコードです。
    マップチップの属性をテストするときに利用して下さい。
            case WM_LBUTTONDOWN:
                g_xp= LOWORD(lParam);
                g_yp= HIWORD(lParam);
                Render();
                return 0L;
        

【演習】

  1. 解像度を設定して Full Screen Mode で描画して下さい。
    解像度と Full Screen の設定は Full Screen でスクロール を参照して下さい。
    自宅のパソコンでは「800*600」を使っていますが、学校のパソコンでは設定できませんでした。
    学校の環境ではプロジェクタが接続されているためでしょうか?。
    設定できる解像度は「ビデオカードやモニタや接続機器など」ハードに依存するので、実行環境に合わせて試して下さい。
  2. BG のスクロールと組み合わせて下さい。
    BG のスクロールは、次の二通りが基本です。
    1. 現在表示されている背景上ではキャラクタだけを動かし、画面の端にきたときに背景をスクロールする。
    2. キャラクタを常に画面中央に表示するように背景をスクロールする。
      背景がスクロールできなくなったらキャラクタを移動する。
  3. マップチップに他の属性を設定して、キャラクタを制御して下さい。
  4. キャラクタが進めるか否かを、毎回(1ドットや2ドットごと)に BG で調べていたのでは、多少マップからズレるのは仕方がありません。
    BG Map に沿ってきっちり動かすには、進行方向の BG を調べるタイミングをセルの境界(16 or 32)に合わせます。
    詳細は BG でキャラクタを制御する を参照して下さい。

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