BG でキャラクタを制御する


Map Chip を背景にキャラクタが歩き回ります。

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

プログラムの説明

  1. Map Chip 画像を組み合わせた背景で、キャラクタの動きを制御します。
    ゲームでは BG を利用してゲームを制御することが良く行われます。
    今回は BG で描画された背景の「草原と海」を認識してキャラクタを動かしてみましょう。
    先頭の画像で緑が草原で、青は海です。海は歩くことが出来ません。
  2. Game1.cs を編集して Map Chip を背景にキャラクタが歩き回るプログラムを作成します。
    プログラムの最初に Image Object Class と BG Object Class を定義します。
    Image Object Class の説明は Image Class でアニメーション を参照して下さい。
    BG Object Class の説明は Mapchip を組み合わせて背景を作成 を参照して下さい。
    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
    
  3. class Game1 の最初に次の領域を宣言して下さい。
    myTexture; が BG に使用するマップチップ画像です。
    charTexture; が BG 上を動き回るキャラクタの画像です。
    Image bunny; でキャラクタの Image Class を定義します。
    direct はキャラクタの向いている方向(0〜3)です。
    BG bg; が Back Ground Object Class の定義です。
            Texture2D   myTexture;     // BG に使用するテクスチャ
            Texture2D   charTexture;   // キャラクタのテクスチャ
            Image       bunny;         // Image Class のバニーガール
            int         direct = 1;    // キャラクタの向き
            BG          bg;            // Back Ground Class
        
  4. int[,] map = new int[ , ] は BG を構成する Chip の並び情報を定義した二次元配列です。
    7 で海を、1で草原を表しています。
        //BG Map Data (縦=38個 608ピクセル, 横=50個 800ピクセル)
        int[,]      map = new int[ , ]
        { { 7,7,7,7,7,7,7,7,7,7,7,7,・・・ },
                ・・・
          { 1,1,1,1,1,1,1,1,1,1,1,1,・・・ },
            ・・・,7,7,7,7,7,7,7,7,7,7,7,7 } };
        
  5. Title Bar にデバッグ情報を表示するメソッドです。
    今回はキャラクタの座標と Map Chip の並び情報の関係を調整するために使用します。
            #region ★Title Bar にデバッグ情報を表示
            public void VerMsg(int x, int y)
            {
                string wstr;
                wstr = "x=" + x.ToString() + "  y=" + y.ToString();
                base.Window.Title = wstr;
            }
            #endregion
        
  6. LoadContent() メソッドで画像をロードして、BG Object Class と Image Object Class を初期化します。
    Chr17.png はキャラクタが前後左右に動き回る様子を2枚のペアでアニメーションする画像です。
    Image(charTexture,1,8) の 1,8 は縦に並んだ8枚の画像を切り分けます。
    キャラクタの座標は 20,15 からスタートします。
                charTexture = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\test\\Chr17.png");
                bunny = new Image(charTexture,1,8);
                bunny.sp_no = 0;
                bunny.pos = new Vector2(20, 15);
        

  7. Maps.bmp がマップチップの画像です。
    BG(myTexture,16) の 16 はマップチップのサイズです。
                myTexture = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\test\\Maps.bmp");
                bg= new BG(myTexture,16);
        
  8. Update() メソッドで矢印キーの操作でキャラクタを動かします。
    上下左右のキーが押されると direct に進む方向を設定します。
    direct の値はキャラクタの画像に対応していて、walk() メソッドでアニメーションしながら動かします。
                if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
                    Keyboard.GetState().IsKeyDown(Keys.Escape)) this.Exit();
    
                // TODO: Add your update logic here
                KeyboardState keyState = Keyboard.GetState();
                if (keyState.IsKeyDown(Keys.Up))    direct = 0;
                if (keyState.IsKeyDown(Keys.Right)) direct = 1;
                if (keyState.IsKeyDown(Keys.Down))  direct = 2;
                if (keyState.IsKeyDown(Keys.Left))  direct = 3;
                //座標の移動
                walk(cat.pos,direct);
        
  9. Draw() メソッドで背景画像とキャラクタを描画します。
    bg.Draw(spriteBatch, map); が map テーブルに従って背景画像を描画するコードです。
    bunny.Draw(spriteBatch); で背景画像の上からバニーガールを描画します。
    次の2行のコードで、進行方向に合わせて2枚の画像を切り替えながらアニメーションします。
    bunny.Loop(gameTime, 200);
    bunny.sp_no = (bunny.sp_no%2) + direct + direct;
                spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
                bg.Draw(spriteBatch, map);
                bunny.Draw(spriteBatch);
                bunny.Loop(gameTime, 200);
                bunny.sp_no = (bunny.sp_no%2) + direct + direct;
                spriteBatch.End();
        
  10. 進行方向(direct)に従ってキャラクタを動かす walk() メソッドです。
    キャラクタの座標から map[,] の二次元座標を計算します。
    キャラクタ座標は矩形の左上なので、実際に動かして座標の微妙な調整を行います。
    +4, +16 などが調整した値です。
    x = ((int)pos.X+4) / 16;
    y = ((int)pos.Y+16) / 16 - 1;
    map[,] の進行方向が草原なら、キャラクタを少しずつ移動します。
    VerMsg(x, y) で変換された座標を表示しています。
    プログラムが完成すれば、コメントアウトして下さい。
            //BG Map Data (縦=38個 608ピクセル, 横=50個 800ピクセル)
            public void walk(Vector2 pos, int dir)
            {   int x=0,y=0;
    
                switch(dir)
                {   case 0: //上
                        x = ((int)pos.X+4) / 16;
                        y = ((int)pos.Y+16) / 16 - 1;
                        if (y >= 0 && map[y, x] == 1)   bunny.pos.Y -= 1;
                        break;
                    case 1: //右
                        x = ((int)pos.X+12) / 16 + 1;
                        y = ((int)pos.Y+4) / 16;
                        if (x < 50 && map[y, x] == 1)   bunny.pos.X += 1;
                        break;
                    case 2: //下
                        x = ((int)pos.X+4) / 16;
                        y = ((int)pos.Y+16) / 16 + 1;
                        if (y < 38 && map[y, x] == 1)   bunny.pos.Y += 1;
                        break;
                    case 3:  //左
                        x = ((int)pos.X+14) / 16 - 1;
                        y = ((int)pos.Y+4) / 16;
                        if (x >= 0 && map[y, x] == 1)   bunny.pos.X -= 1;
                        break;
                }
                VerMsg(x, y);
            }
        

【演習】

  1. 適当なキャラクタの画像を調達してきて動かしてみて下さい。
    この手の画像はネットで検索すれば沢山見つかるはずです。
  2. 進行方向に向かって3枚以上の画像でアニメーションするキャラクタを使ってみて下さい。
  3. 草原と海だけで無く、もっと複雑な背景を描画して、キャラクタを操作して下さい。

【NOTE】

キャラクタが進めるか否かを、毎回(1ドットや2ドットごと)に BG で調べていたのでは、多少マップからズレるのは仕方がありません。
BG Map に沿ってきっちり動かすには、進行方向の BG を調べるタイミングをセルの境界(16 or 32)に合わせます。
例えば、次のようにします。
  1. 横方向に移動するときは、縦の座標を16の境界(0,16,32,48,64, ...)に合わせます。
  2. 同様に縦方向に移動するときは、横の座標を16の境界(0,16,32,48,64, ...)に合わせます。
  3. 進行方向を変えるときは、縦/横共に16の境界に来たタイミングで BG を調べて切り替えます。
    pos がキャラクタの座標とすると、次のようになります。
    if ((int)pos.X % 16 == 0 && (int)pos.Y % 16 == 0)
    //この条件で BG Map を調べて進行方向を変えます
  4. キャラクタがマップからズレるときは、描画のときに調整して下さい。
    例えば次のようにします。
        Vector2 wpos;
    
        wpos.X = pos.X - 10;
        wpos.Y = pos.Y - 8;
        //wpos の座標に描画する
        
  5. このとき注意しなければならないことは、キャラクタの座標が16の倍数になるように増減しなければならないことです。
    例えば、1ドットや2ドットずつ動くのはOKですが、3ドットずつ動くと判定されないセルが出てきます。
    またキャラクタの初期座標も16の倍数に設定して下さい。

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

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

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