Map Chip を組み合わせて背景を作成

上の画像のように Map Chip を組み合わせて BG(Back Ground) を表示します。

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

プログラムの説明

  1. Map Chip 画像をタイルのように組み合わせて背景を描画するプログラムを作成します。
    RPG では World Map や Field Map やダンジョンなど多くの場面で BG(背景画像)が使われます。
    RPG に限らず、他のゲームでも BG(Back Ground) が良く使われます。
    Map Chip(画面右) は背景を作成するパーツの集まりで、これをタイルのように配置して大きな背景画面を構成します。
    今回使用する Map Chip は、先頭の画像のように「16 dot * 16 dot」の Chip を横に16個、縦に16個並べた画像です。
    BG を使えばウインドウの何十倍もの大きな背景画像を作成することが簡単に出来ます。
    BG で作成した画像を背景に、セルの属性を利用してキャラクタを制御するゲームも良く見かけます。
    また、ゲームの進行に合わせて背景画像の一部を変えるとき(ドアの開閉や宝箱の蓋など)にも BG が使われます。
    BG を利用して、次のような使い方が考えられます。
  2. メニューから [ファイル][新規作成][プロジェクト] で新しいプロジェクトを作成して下さい。
    Game1.cs を編集して Map Chip を組み合わせて BG(Back Ground) を表示するプログラムを作成します。
    プログラムの最初に BG Object Class を定義します。
    BG Object Class の説明は、このページの後部に掲載しています。
    namespace Main
    {
        #region ★BG(Back Ground) Object Class
        public class Image
        {
            //BG Object Class を定義する
        }
        #endregion
    
  3. class Game1 の最初に次の領域を宣言して下さい。
    myTexture; が BG に使用するマップチップ画像です。
    BG bg; が Back Ground Object Class の定義です。
    int[,] map = new int[4, 30] は BG を構成する Chip の並び情報を定義した二次元配列です。
    上の行から「2番,3番,4番,5番」のセルを行ごとに並べて描画します。
        public class Game1 : Microsoft.Xna.Framework.Game
        {
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
            Texture2D   myTexture;     // 描画に使用するテクスチャ
            BG          bg;            // Back Ground Class
    
            //BG Map Data (縦=20個 320ピクセル, 横=30個 480ピクセル)
            int[,]      map = new int[4, 30]
            { { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 },
              { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 },
              { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 },
              { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 } };
        
  4. コンストラクタで map に合わせて、ウインドウのサイズを小さくしています。
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
                graphics.PreferredBackBufferWidth = 480;
                graphics.PreferredBackBufferHeight = 320;
            }
        
  5. LoadContent() で Map Chip 画像をロードしてから bg を初期化します。
    16 は Map Chip のサイズです。
            protected override void LoadContent()
            {
                // Create a new SpriteBatch, which can be used to draw textures.
                spriteBatch = new SpriteBatch(GraphicsDevice);
    
                // TODO: use this.Content to load your game content here
                myTexture = Texture2D.FromFile(graphics.GraphicsDevice, "c:\\data\\test\\Maps.bmp");
                bg= new BG(myTexture,16);
            }
        
  6. Draw() メソッドで Map Chip を描画します。
    bg.Draw(spriteBatch, map); が map テーブルに従って背景画像を描画するコードです。
            protected override void Draw(GameTime gameTime)
            {
                graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    
                // TODO: Add your drawing code here
                spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
                bg.Draw(spriteBatch, map);
                spriteBatch.End();
    
                base.Draw(gameTime);
            }
        

BG Class 全体の説明

  1. public class BG が BG(Back Ground) を描画するクラスです。
    img が Map Chip の画像です。
    siz はマップチップの縦と横の共通のサイズで、コンストラクタで指定します。
    xn,yn は横と縦のマップチップの枚数で、siz と Map Chip に使用する画像サイズから計算します。
            #region ★背景を描画するバックグラウンドクラス
            public class BG
            {
                public Texture2D img;       //画像の指定
                public int       siz;       //マップチップのサイズ
                public int       xn,yn;     //横と縦の枚数
    
                //コンストラクタ
                public BG(Texture2D Img, int Siz)
                {   img = Img;
                    siz = Siz;
                    xn = img.Width / siz;
                    yn = img.Height / siz;
                }
        
  2. 三種類の Draw() メソッドを用意しました。
    1. Draw(SpriteBatch spBatch)
      Map Chip 画像全体を描画するメソッドで、画像の確認を行うときに使います。
    2. Draw(SpriteBatch spBatch, Vector2 pos, int No)
      No で指定された一枚の Map Chip を、pos の座標に描画します。
    3. Draw(SpriteBatch spBatch, int[,] t)
      二次元配列 t で指定された Map Chip の並び情報を使って背景画面を描画します。
      背景画面の大きさは Map Chip のサイズ(siz) と、二次元配列(t) の大きさで決まります。
                //画像全体の描画
                public void Draw(SpriteBatch spBatch)
                {
                    spBatch.Draw(img, new Vector2(0, 0), Color.White);
                }
                //マップチップの描画
                public void Draw(SpriteBatch spBatch, Vector2 pos, int No)
                {   int xw,yw;
    
                    if (No < xn*yn)
                    {   xw= No%xn;
                        yw= No/xn;
                        spBatch.Draw(img,pos, new Rectangle(xw*siz,yw*siz,siz,siz),Color.White);
                    }
                }
                //マップテーブルを描画
                public void Draw(SpriteBatch spBatch, int[,] t)
                {   int     x,y;
                    Vector2 pos;
    
                    for(y=0; y < t.GetLength(0); y++)
                        for(x=0; x < t.GetLength(1); x++)
                        {   pos.Y = y*siz;
                            pos.X = x*siz;
                            Draw(spBatch,pos,t[y,x]);
                        }
                }
            }
        
  3. 背景画像を作成するツール(Mapedit)を使うと Map Chip の並びデータを TEXT FILE に保存することが出来ます。
    これを二次元配列の初期値として設定するには、データ量が多いこともあり、結構手間がかかります。
    そこで、TEXT 形式の FILE からデータを入力して二次元配列に格納するメソッドを BG Class に追加しました。
    また TEXT 形式のデータを入力して、一次元配列に格納するメソッドも用意しました。
    ファイルの入出力を行うので using System.IO; を設定して下さい。
            //Map Table にデータを読み込む
            public bool GetTxt(string file, int[,] t)
            {   int    pt,x,y;
                string wstr;
    
                if (!File.Exists(file)) return false;   //ファイルの有無をチェック
                StreamReader reader = new StreamReader(file, false);
                for(y=0; y<t.GetLength(0); y++)
                {   do
                    {   wstr=reader.ReadLine();
                        if (wstr == null)
                        {   reader.Close();
                            return false;
                        }
                    }   while(wstr[0]=='/');
                    for(x=0; x<t.GetLength(1); x++)
                    {   pt = wstr.IndexOf(',');
                        t[y,x] = Convert.ToInt32(wstr.Substring(0,pt));
                        wstr = wstr.Substring(pt+1);
                    }
                }
                reader.Close();
                return true;
            }
        
            //一次元配列にデータを読み込む
            public bool GetTxt(string file, int[] t)
            {
                    :
                    :
            }
        
  4. ゲームではウインドウの何十倍もの背景画像を使用して、スクロールしながらプレイすることが良くあります。
    一枚の画像のスクロールは簡単なのですが、マップチップを並べた BG をドット単位にスクロールするのは一苦労です。
    そこで BG Object Class にドット単位でスクロールするメソッドを追加しました。
    またウインドウの任意の座標(矩形領域)を指定して、BG を描画できるようになっています。
            //マップテーブルをドット単位に描画
            //rect=描画する矩形領域   offset=map[,]のオフセット
            public void Draw(SpriteBatch spBatch, int[,] t, Rectangle rect, Vector2 offset)
            {
                    :
                    :
            }
        

【演習】

次の map 配列を定義して BG を描画して下さい。
ページ先頭の背景が描画されたら正解です。
//BG Map Data (縦=20個 320ピクセル, 横=30個 480ピクセル)
int[,]      map = new int[ , ]
{ { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
  { 1,64,65,1,1,64,65,1,1,74,75,74,75,74,75,74,75,74,75,74,75,1,1,64,65,1,1,64,65,1 },
  { 1,80,81,1,1,80,81,1,1,90,91,90,91,90,91,90,91,90,91,90,91,1,1,80,81,1,1,80,81,1 },
  { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
  { 1,1,40,41,1,40,41,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
  { 1,1,56,57,1,56,57,1,1,1,1,1,1,1,1,1,1,1,1,1,1,42,43,1,42,43,1,68,69,1 },
  { 1,1,40,41,1,40,41,1,1,72,73,72,73,72,73,72,73,72,73,1,1,58,59,1,58,59,1,84,85,1 },
  { 1,1,56,57,1,56,57,1,1,88,89,88,89,88,89,88,89,88,89,1,1,42,43,1,42,43,1,1,1,1 },
  { 1,1,40,41,1,40,41,1,1,1,1,1,1,1,1,1,1,1,1,1,1,58,59,1,58,59,1,68,69,1 },
  { 1,1,56,57,1,56,57,1,1,1,1,1,1,1,1,1,1,1,1,1,1,42,43,1,42,43,1,84,85,1 },
  { 1,1,40,41,1,40,41,1,1,96,97,1,96,97,1,96,97,1,96,97,1,58,59,1,58,59,1,1,1,1 },
  { 1,1,56,57,1,56,57,1,1,112,113,1,112,113,1,112,113,1,112,113,1,42,43,1,42,43,1,68,69,1 },
  { 1,1,40,41,1,40,41,1,1,128,129,1,128,129,1,128,129,1,128,129,1,58,59,1,58,59,1,84,85,1 },
  { 1,1,56,57,1,56,57,1,1,144,145,1,144,145,1,144,145,1,144,145,1,42,43,1,42,43,1,1,1,1 },
  { 1,1,40,41,1,40,41,1,1,1,1,1,1,1,1,1,1,1,46,47,1,58,59,1,58,59,1,46,47,1 },
  { 1,1,56,57,1,56,57,1,32,33,1,32,33,1,32,33,1,1,62,63,1,1,1,1,1,1,1,62,63,1 },
  { 1,1,1,1,1,1,1,1,48,49,1,48,49,1,48,49,1,1,162,163,162,163,162,163,162,163,164,165,162,163 },
  { 1,1,32,33,1,32,33,1,226,227,226,227,226,227,226,227,46,47,178,179,178,179,178,179,178,179,180,181,178,179 },
  { 1,1,48,49,1,48,49,1,242,243,242,243,242,243,242,243,62,63,166,167,168,169,166,167,168,169,166,167,168,169 },
  { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,182,183,184,185,182,183,184,185,182,183,184,185 } };

【NOTE】

MapChip を組み合わせて背景画像を作成するツール(Mapedit)を開発しました。
説明は「超初心者のプログラム入門/C言語 Windows/Map Chip で背景を表示」を参照して下さい。

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

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

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