烏賊先生のプログラミング道場
ゲーム プログラミング 道場

§ ゲーム製作道具 §

 マップ エディタ

烏賊先生のプログラミング道場

ロールプレイングゲームやスクロール型アクションゲーム等の画面(仮想スクリーン)を任意の大きさで作成する為のエディタです。マップチップも任意の大きさの物を使用する事が出来ます。

先ず、マップのサイズとマップチップのサイズを入力してSetボタンをクリックします(デフォルトの儘で良ければ、必要有りません)。左側のマップ描画領域に指定のサイズでグリッドが描かれます。

右側のマップチップ指定領域をクリックして使用するマップチップを選択します。其の上のチェックボックスで垂直軸(V)や水平軸(H)の反転、チェックボックスで0、90、180、270度の回転の属性をマップチップに付加する事が出来ます。マップチップ番号と属性値が表示されます。

左側のマップ描画領域をクリックすると、選択されて居るマップチップがセットされます。ドラッグすると、連続してセットする事が出来ます。

Saveボタンをクリックすると、画面データがグリッド毎に、マップチップ番号と属性値のセットで、テキスト形式で保存されます。猶、先頭行には、マップチップの画像のパスが、2行目には、マップのサイズとマップチップのサイズが記録されます。

Loadボタンをクリックすると、保存して居るマップデータを読み込む事が出来ます。此れに依り、製作途中のマップデータの続きを作成する事が出来ます。

Image Saveボタンをクリックすると、マップデータを画像と仕て保存する事が出来ます。此れに依り、マップをマップデータから再現するのではなく、画像と仕てゲーム画面に貼り付ける事が出来ます。

Image Loadボタンをクリックすると、上記のImage Saveで保存した画像を読み込む事が出来ます。任意の画面サイズで引き続き画像を作成する事が出来ますが、マップデータは読み込まれません。

Map Chip Image Loadボタンをクリックすると、任意のマップチップを読み込む事が出来ます。マップチップのサイズが異なる場合は、其の幅と高さを入力して、Setボタンをクリックして下さい。

マップチップの0番目を透明チップに変更しました。総てをマップチップで埋め尽くす場合は、問題有りませんでしたが、背景画を併用する場合の透明部分が必要な場合の為の変更です。

Code Saveボタンは廃止しました。マップデータからマップを描画し、仮想スクリーンにデータをセットするコードを生成する予定でしたが、此のページに、描画の為のサンプルコードを掲載したので、其の必要が無く成りました。

背景色を指定出来る様に仕ました。但し、此のエディタで配色を確認する為の物で、データと仕ては保存されません。実際に使用するプログラムの中で自由に設定して下さい。




上記のマップエディタで作成したマップデータファイルを読み込んで描画するコードを下記に示します。変数のスコープ等は、実際にゲームに使用する時に便利な様に設定して居ますが、適宜変更して下さい。

前景用のGraphicsオブジェクトは、此処では使用しませんが、此れも実際にゲームに使用する時にキャラクタの描画用に利用する為に設定して居ます。

マップチップ用画像は、マップデータファイルに記録されて居るパスか、マップデータファイルが有るパスに無いと、マップは描画されません。マップデータファイル(テキストファイル)のパスを書き換える等の対処を仕て下さい。

Visual Basic 2005/2008/2010
Imports System.IO

Public Class MapDisp
  Private Structure MapData
    Dim Number As Integer     ' チップ番号
    Dim Attr As Integer       ' チップ属性
  End Structure

  Private Bm As Bitmap        ' マップチップ画像
  Private Gb, Gf As Graphics  ' マップ描画用(Gb:背景用、Gf:前景用)
  Private Gc As Graphics      ' マップチップ描画用
  Private Mw, Mh As Integer   ' マップサイズ
  Private Cw, Ch As Integer   ' マップチップサイズ
  Private Map(,) As MapData   ' マップデータ(仮想スクリーン)

  Private Sub btnLoad_Click(sender As System.Object, e As System.EventArgs) Handles btnLoad.Click
    If dlgOpen.ShowDialog() = Windows.Forms.DialogResult.OK Then
      Dim F As String = dlgOpen.FileName
      Dim P As String = F.Substring(0, F.LastIndexOf("\"c) + 1)
      Dim S, D() As String
      Using Sr As StreamReader = New StreamReader(F, System.Text.Encoding.Default)
        ' マップチップファイルの読込
        F = Sr.ReadLine()
        ' 基本サイズの取得
        S = Sr.ReadLine() : D = S.Split(","c)
        Mw = Integer.Parse(D(0))
        Mh = Integer.Parse(D(1))
        Cw = Integer.Parse(D(2))
        Ch = Integer.Parse(D(3))
        ReDim Map(Mw - 1, Mh - 1)
        ' マップデータの取得
        For I As Integer = 0 To (Mh - 1)
          S = Sr.ReadLine() : D = S.Split(","c)
          For J As Integer = 0 To (Mw - 1)
            Map(J, I).Number = Integer.Parse(D(J * 2))
            Map(J, I).Attr = Integer.Parse(D(J * 2 + 1))
          Next
        Next
        Sr.Close()
      End Using
      ' マップチップ用Graphicsオブジェクトの生成
      With picChip
        .Size = New Size(Cw, Ch)
        .Image = New Bitmap(.Width, .Height)
        Gc = Graphics.FromImage(.Image)
      End With
      Gc.Clear(Color.White)
      ' マップ用Graphicsオブジェクトの生成
      With picDisp
        .Size = New Size(Mw * Cw, Mh * Ch)
        .BackgroundImage = New Bitmap(.Width, .Height)
        .Image = New Bitmap(.Width, .Height)
        Gb = Graphics.FromImage(.BackgroundImage) ' 背景用(マップを描画)
        Gf = Graphics.FromImage(.Image)           ' 前景用(キャラクタを描画・未使用)
      End With
      Gb.Clear(Color.White)
      Gf.Clear(Color.Transparent)
      ' マップチップ画像の読込
      If Not File.Exists(F) Then
        F = P & F.Substring(F.LastIndexOf("\"c) + 1)
        If Not File.Exists(F) Then
          MessageBox.Show("Map Chip Image not found !")
          Exit Sub
        End If
      End If
      Bm = New Bitmap(F)
      ' マップの描画
      Dim N, A, X, Y As Integer
      Dim ChipCol As Integer = Bm.Width \ Cw
      For I As Integer = 0 To (Mh - 1)
        For J As Integer = 0 To (Mw - 1)
          N = Map(J, I).Number
          A = Map(J, I).Attr
          X = (N Mod ChipCol) * Cw
          Y = (N \ ChipCol) * Ch
          Gc.DrawImage(Bm, New Rectangle(0, 0, Cw, Ch), New Rectangle(X, Y, Cw, Ch), _
            GraphicsUnit.Pixel)
          picChip.Image.RotateFlip(A)
          picChip.Refresh()
          Gb.DrawImage(picChip.Image, J * Cw, I * Ch)
          picDisp.Refresh()
        Next
      Next
    End If
  End Sub

  Private Sub btnBackColor_Click(sender As System.Object, e As System.EventArgs) _
    Handles btnBackColor.Click
    If dlgColor.ShowDialog() = Windows.Forms.DialogResult.OK Then
      pnlDisp.BackColor = dlgColor.Color
    End If
  End Sub
End Class

Visual C# 2005/2008/2010
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace MapDisp
{
  public partial class MapDisp : Form
  {
    public MapDisp()
    {
      InitializeComponent();
    }

    private struct MapData
    {
      public int number;  // チップ番号
      public int attr;    // チップ属性
    }

    private Bitmap bm;
    private Graphics gb, gf;
    private Graphics gc;
    private int mw, mh;
    private int cw, ch;
    private MapData[,] map;

    private void btnLoad_Click(object sender, EventArgs e)
    {
      if (dlgOpen.ShowDialog() == System.Windows.Forms.DialogResult.OK)
      {
        string f = dlgOpen.FileName;
        string p = f.Substring(0, f.LastIndexOf('\\') + 1);
        string s = "";
        string[] d;
        using (StreamReader sr = new StreamReader(f, System.Text.Encoding.Default))
        {
          // マップチップファイルの読込
          f = sr.ReadLine();
          // 基本サイズの取得
          s = sr.ReadLine(); d = s.Split(',');
          mw = int.Parse(d[0]);
          mh = int.Parse(d[1]);
          cw = int.Parse(d[2]);
          ch = int.Parse(d[3]);
          map = new MapData[mw, mh];
          // マップデータの取得
          for (int i = 0; i < mh; i++)
          {
            s = sr.ReadLine(); d = s.Split(',');
            for (int j = 0; j < mw; j++)
            {
              map[j, i].number = int.Parse(d[j * 2]);
              map[j, i].attr = int.Parse(d[j * 2 + 1]);
            }
          }
          sr.Close();
        }
        // マップチップ用Graphicsオブジェクトの生成
        picChip.Size = new Size(cw,ch);
        picChip.Image = new Bitmap(picChip.Width,picChip.Height);
        gc = Graphics.FromImage(picChip.Image);
        gc.Clear(Color.White);
        // マップ用Graphicsオブジェクトの生成
        picDisp.Size = new Size(mw*cw,mh*ch);
        picDisp.BackgroundImage = new Bitmap(picDisp.Width,picDisp.Height);
        picDisp.Image = new Bitmap(picDisp.Width,picDisp.Height);
        gb = Graphics.FromImage(picDisp.BackgroundImage); // 背景用(マップを描画)
        gf = Graphics.FromImage(picDisp.Image);           // 前景用(キャラクタを描画・未使用)
        gb.Clear(Color.White);
        gf.Clear(Color.Transparent);
        // マップチップ画像の読込
        if (!File.Exists(f))
        {
          f = p + f.Substring(f.LastIndexOf('\\') + 1);
          if (!File.Exists(f))
          {
            MessageBox.Show("Map Chip Image not found !");
            return;
          }
        }
        bm = new Bitmap(f);
        // マップの描画
        int n, a, x, y;
        int chipcol = bm.Width / cw;
        for (int i = 0; i < mh; i++)
        {
          for (int j = 0; j < mw; j++)
          {
            n = map[j, i].number;
            a = map[j, i].attr;
            x = (n % chipcol) * cw;
            y = (n / chipcol) * ch;
            gc.DrawImage(bm, new Rectangle(0, 0, cw, ch), new Rectangle(x, y, cw, ch),
              GraphicsUnit.Pixel);
            picChip.Image.RotateFlip((RotateFlipType)a);
            picChip.Refresh();
            gb.DrawImage(picChip.Image, j * cw, i * ch);
            picDisp.Refresh();
          }
        }
      }
    }

    private void btnBackColor_Click(object sender, EventArgs e)
    {
      if (dlgColor.ShowDialog() == System.Windows.Forms.DialogResult.OK)
      {
        pnlDisp.BackColor = dlgColor.Color;
      }
    }
  }
}

ダウンロード