C#でRPGを作る。第一回：Windows Formsでマップを表示しよう。

RPG好きですか？好きですよね。作りましょう。
C#好きですか？好きですよね。使いましょう。
というわけでC#で適当にRPG作っていくことにします。

さて、C#でゲームを作るのは良いとして、フレームワーク（ライブラリ？）はどうしましょうか。
今ならUnity一択ですかね。
XNAは開発止まったらしいですね。
MonoGameは昔触った時はいい感触だったんですけど、全然流行ってないですね。
DXLibもいいですよね。私が最初にゲーム作ったときに使ったのがDXライブラリなんですよ。

というわけでフレームワークは選り取り見取りですが、使い方調べるのめんどくさいですよね。
真面目に作る気がないから、パフォーマンスとか使いやすさとかあんま考えたくないですもん。
とにかく楽なのがいい。

というわけでフレームワークなしでRPGを作っていきます。
正確に言えばWindows Formsで描画。
なんでWindows Formsかって？
私が使い慣れてるからです。

えっ、Windows Formsは古臭い？
ゲームに向いてない？
せめてWPFにしろ？
まあいいじゃないですか。Windows Formsは楽ですよきっと。

さて、さっそくRPG作りに入りますが、RPGって何でしょう？
私が思うにRPG＝マップですね。
想像してくださいよ。フィールドマップがどどーんと描画されてるだけで「あっ、RPGだ！」って感じるでしょう？
ですので第一回の目的は「マップ描画」でいこうと思います。

![スクリーンショット 2016-10-03 18.58.50.png](https://qiita-image-store.s3.amazonaws.com/0/119431/263ddd4f-a8f3-d450-a4d5-374229cf1bfa.png)

プログラミング以前の話ですが、ゲームには画像が必要ですね。
3Dとか全くわかりませんので2Dゲー一択です。
ドット絵エディタはEDGEがいいとか10年前に聞いた覚えがありますが、最近の流行りはとんと知りません。
ちなみに左から草原、山、家です。

![スクリーンショット 2016-10-03 19.05.49.png](https://qiita-image-store.s3.amazonaws.com/0/119431/0c8f548d-fa4d-6505-5ce0-4278764b28a7.png)

ゲーム制作画面です。
FormにPictureBoxとTimerを貼っただけです。
PictureBoxにゲーム画面を描画して、Timerで描画を更新するだけです。
楽ちんですね。

```c#
    /// <summary>
    /// クラスの名前に迷ったらとりあえずManagerをつければいい。
    /// </summary>
    public class MapManager
    {
        public Bitmap MapImage { get; set; }
        public int MapChipSize = 32;
        public List<Map> Maps { get; private set; } = new List<Map>();
        //指定したマップチップのMapImage上での開始位置を返します。
        public Point GetMapChipPoint(int nth)
        {
            return new Point(nth * MapChipSize, 0);
        }
        //指定したマップチップの画像を返します
        public Bitmap GetMapChip(int nth)
        {
            var mcpoint = GetMapChipPoint(nth);
            Rectangle rect = new Rectangle(mcpoint.X, mcpoint.Y, MapChipSize, MapChipSize);
            Bitmap bmpNew = MapImage.Clone(rect, MapImage.PixelFormat);
            return bmpNew;
        }
        //指定したマップの画像を返します。
        public Bitmap GetMap(int nth)
        {
            var mapdata = this.Maps[nth];
            var xLen = mapdata.MapChips.GetLength(1);
            var yLen = mapdata.MapChips.GetLength(0);
            var bmp = new Bitmap(xLen * this.MapChipSize, yLen * this.MapChipSize);

            Graphics g = Graphics.FromImage(bmp);
            for(int y = 0; y < yLen; y++)
            {
                for (int x = 0; x < xLen; x++)
                {
                    var mapchip = this.GetMapChip(mapdata.MapChips[y, x]);
                    g.DrawImage(mapchip, new PointF(x * this.MapChipSize, y * this.MapChipSize));
                    mapchip.Dispose();
                }
            }
            g.Dispose();
            return bmp;
        }
        public MapManager()
        {
            this.MapImage = (System.Drawing.Bitmap)Bitmap.FromFile("data/image/map.png");
            //今回表示するマップのマップチップ配列。0:草原,1:山,2:家
            var integerMapChips = new int[,] {
                { 0,0,0,0,0,0,0,0,0 },
                { 0,0,0,0,0,0,0,0,0 },
                { 0,0,2,0,0,0,0,0,0 },
                { 0,0,0,0,1,0,0,0,0 },
                { 0,1,0,0,0,0,0,0,0 },
                { 0,0,0,0,0,0,0,0,0 },
                { 0,0,0,0,0,0,0,0,0 }
            };
            this.Maps.Add(new Map() { MapChips = integerMapChips });
        }
    }
    /// <summary>
    /// これいるの？
    /// </summary>
    public class Map
    {
        public int[,] MapChips { get; set; }
    }
```
integerMapChipsの整数二次元配列をBitmap画像に変換するコードです。
C#での画像の扱い方はググればたくさん情報が出てくるので何も苦労しませんでした。

```c#
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            this.pictureBox1.Refresh();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            
            Graphics g = e.Graphics;
            g.Clear(Color.Black);
            using (var map = Game.MapManager.GetMap(0))
            {
                g.DrawImage(map, PointF.Empty);
            }
        }
    }
```
timerで定期的にpictureboxの再描画を命じるだけのコードです。
超シンプルですね。

![スクリーンショット 2016-10-03 19.39.25.png](https://qiita-image-store.s3.amazonaws.com/0/119431/f6055707-979a-8fff-210e-3c364839ab33.png)

全米が震撼するRPGの出来上がりです。
あの家にはいったい誰が住んでいるのでしょうか？
あの二つの山には一体何の意味があるんでしょうか。
超ドキドキしますね。

以上です。この記事作るだけで満足したので第二回はなさそうです。