BG を切り替える

秘密の通路をくぐると、ダンジョンの BG に切り替わります。

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

プログラムの説明

  1. 背景画像から秘密の通路の前に立っていることを検出して、ダンジョンの BG に切り替えます。
    ここまでプログラム出来ればダンジョンの BG に切り替えるのは簡単でしょう。
  2. BG で描画された背景の画像を認識してキャラクタを動かすのですが、マップチップが多くなると直接マップチップの番号で判定することが難しくなります。
    次の数字の並びは、マップチップの属性を定義したテキストファイル(MapSatt.txt) の一部で、マップチップと一対一に対応しています。
    0 が通ることの出来ないセルで、1 が通ることが出来るセルです。
    3 がダンジョン入口で、ここと通ると BG を切り替えます。
    ダンジョンの BG にも元の画面に戻る出口を用意しています。
    2 は宝箱ですが、今回は使いません。
    //MapS.png の属性(0:通行不可  1:通行可  2:宝箱  3:ワープ)  Y=24, X=16
      1,  1,  1,  1,  1,  1,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
      1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
                      :
      0,  0,  0,  0,  3,  3,  0,  0,  1,  1,  2,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  0,  0,  1,  1,
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,  3,  0,  0,  1,  1,
                      :
    
  3. Game1.cs を編集して BG を切り替えながらキャラクタが歩き回るプログラムを作成します。
    プログラムの最初に Image Object Class と BG Object Class を定義します。
    namespace Main
    {
        #region ★Image Object Class
        public class Image
        {
            //Image Object Class を定義する
        }
        #endregion
    
        #region ★BG(Back Ground) Object Class
        public class BG
        {
            //BG(Back Ground) Object Class を定義する
        }
        #endregion
    
  4. class Game1 の最初に次の領域を宣言して下さい。
    myTexture; が BG に使用するマップチップ画像です。
    charTexture; が BG 上を動き回るキャラクタの画像です。
    Image bunny; でキャラクタの Image Class を定義します。
    direct はキャラクタの向いている方向(0〜3)です。
    BG bg; が Back Ground Object Class の定義です。
    map1 と map2 が背景画像とダンジョンの画像のマップチップの並び情報です。
    att がマップチップの属性を定義したテーブルです。
    mapflag は背景画像とダンジョンの画像の切替フラグです。
            Texture2D   myTexture;     // 描画に使用するテクスチャ
            Texture2D   charTexture;   // キャラクタのテクスチャ
            Image       bunny;         // Image Class のバニーガール
            int         direct;        // キャラクタの向き
            BG          bg;            // Back Ground Class
            //BG Map Data (縦=38個 608ピクセル, 横=50個 800ピクセル)
            int[,]      map1 = new int[38, 50]; // 一枚目のマップ
            int[,]      map2 = new int[38, 50]; // 二枚目のマップ
            int[]       att  = new int[24*16];  // Mapchip の属性(24*16)
            bool        mapflag = true;         // 一枚目と二枚目のフラグ
        
  5. LoadContent() メソッドで画像をロードして、BG Object Class と Image Object Class を初期化します。
    Chr17.png はキャラクタが前後左右に動き回る様子を2枚のペアでアニメーションする画像です。
    Image(charTexture,1,8) の 1,8 は縦に並んだ8枚の画像を切り分けます。
    キャラクタの座標は 192,160 からスタートします。
                charTexture = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\test\\Chr17.png");
                bunny = new Image(spriteBatch,charTexture,1,8);
                direct= 0;          //進行方向
                bunny.sp_no = 0;
                bunny.pos = new Vector2(192, 160);
                bunny.vect.Y = -1;
        

  6. MapS.png がマップチップの画像です。
    BG(myTexture,16) の 16 はマップチップのサイズです。
    chenge1.txt と chenge2.txt がマップチップの並び情報がタイプされたファイルです。
    このファイルは MapChip を組み合わせて背景画像を作成するツール(MapEdit)で作成することが出来ます。
    MapSatt.txt は先に説明したマップチップの属性がタイプされたファイルです。
                myTexture = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\test\\MapS.png");
                bg = new BG(spriteBatch,myTexture,16);
                bg.GetTxt("C:\\data\\test\\chenge1.txt",map1);
                bg.GetTxt("C:\\data\\test\\chenge2.txt",map2);
                bg.GetTxt("C:\\data\\test\\MapSatt.txt", att);
        
  7. Update() メソッドでキャラクタの移動と、KeyCheck() 関数でキーの操作を検出します。
                // TODO: Add your update logic here
                bunny.Move();       //キャラクタの移動
                KeyCheck();         //キーの操作と進行方向のチェック
                base.Update(gameTime);
        
  8. Draw() メソッドで BG とキャラクタを描画します。
    mapflag の状態で map1 と map2 のどちらを描画するかを決めます。
    bunny をそのまま描画すると BG MAP から少しずれるので X,Y 座標とも調整しています。
    bunny.Draw(spriteBatch,pos) で背景画像の上からキャラクタを描画します。
                spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
                if (mapflag)    bg.Draw(map1);
                else            bg.Draw(map2);
                bunny.Loop(gameTime, 200);
                bunny.sp_no = (bunny.sp_no % 2) + direct + direct;
                pos.X = bunny.pos.X-5;
                pos.Y = bunny.pos.Y-12;
                bunny.Draw(pos);
                spriteBatch.End();
        
  9. キーの操作を検出して、進行方向を変える KeyCheck() メソッドです。
    16ドットのセルの境界でキーの操作を検出します。
    bunny の移動ベクトルをクリアして、キーが押されている方向を direct に設定します。
    キーが押されていないときは、そのままリターン(その場で停止)します。
    進行方向の BG の属性を GetAtt() で sel に取得します。
    direct の方向に進めるとき、移動ベクトルを設定します。
            private void KeyCheck()
            {   KeyboardState keyState;
                int     sel;
    
                //セルの切れ目でキーを調べる
                if ((int)bunny.pos.X % 16 != 0 || (int)bunny.pos.Y % 16 != 0) return;
                bunny.vect.X = 0;
                bunny.vect.Y = 0;
                keyState = Keyboard.GetState();
                if (keyState.IsKeyDown(Keys.Up))         direct = 0;
                else if (keyState.IsKeyDown(Keys.Right)) direct = 1;
                else if (keyState.IsKeyDown(Keys.Down))  direct = 2;
                else if (keyState.IsKeyDown(Keys.Left))  direct = 3;
                else return;
    
                sel = GetAtt(direct, bunny.pos);
                if (sel==-1)    return;     //画面の外
                //通路(BG の切り替え)
                if (att[sel] == 3)  mapflag = !mapflag;
                if (att[sel] != 1)  return; //その方向には進めない
                switch(direct)
                {
                    case 0:     //上
                        bunny.vect.Y = -2;  break;
                    case 1:     //右
                        bunny.vect.X = 2;   break;
                    case 2:     //下
                        bunny.vect.Y = 2;   break;
                    case 3:     //左
                        bunny.vect.X = -2;  break;
                }
            }
        
  10. 進行方向の BG の属性を調べる GetAtt() メソッドです。
    mapx, mapy に pos に対応する map[,] の Index を求めます。
    進行方向に合わせて、隣のセルに設定します。
    map[,] の領域外をアクセスすると落ちるので、リミットチェックを行います。
    mapflag に従ってセルの属性をリターンします。
            public int GetAtt(int houko, Vector2 pos)
            {   int mapx, mapy;
    
                mapx = (int)(pos.X / 16);
                mapy = (int)(pos.Y / 16);
                switch(houko)
                {
                    case 0:     //上
                        mapy -= 1;  break;
                    case 1:     //右
                        mapx += 1;  break;
                    case 2:     //下
                        mapy += 1;  break;
                    case 3:     //左
                        mapx -= 1;  break;
                }
                if (houko>3 || mapx<0 || mapx>=map1.GetLength(1) || mapy<0 || mapy>=map1.GetLength(0))
                {   Console.WriteLine("Map Index Limit Error X={0} Y={1}",pos.X,pos.Y);
                    mapx = 0;
                    mapy = 0;
                    return -1;
                }
                if (mapflag)    return (map1[mapy, mapx]);
                return  (map2[mapy, mapx]);
            }
        

【演習】

  1. 3枚以上の BG を使って、切り替えてみて下さい。
  2. BG の切り替えと BG のスクロールを組み合わせて下さい。

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

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

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