自作RPG|公開した素人マップエディタの詳細説明書

勘違いしながらどハマりしながら作り上げる爺の『JavaScript奮闘記』。爺のくせにゲームのプログラミングに興味を持ってしまいました。

ポク太郎です。

自作RPGの製作のため、マップエディタも自作して公開してみました。誰か使ってくれるかな。

その操作方法・詳細仕様・出力フォーマット、RPG本体のプログラムでデータをどう使うかなどを説明した詳細説明書です。

前提はドラクエ型のマップ遷移方式、ドラクエ型の敵エンカウント方式です。


素人制作マップエディタの画面構成

素人制作マップエディタ

こんな見た目。

自作マップエディタ説明図

タイルチップ画像・出力フォーマットはポク太郎仕様です。決め打ちなのでマップデータを出力した後、ご自身で変換・使えるフォーマットに作り直す必要があります。

マップエディタ各部位と操作方法

自作マップエディタ説明図

マップエディタの画面構成
チップ選択 タイルチップを選択する部分。レイヤに別れており、上部の[背景][地形][キャ][イベ]をクリックして切り替え。

[背景]…海・陸地・床とか。ドラクエ家屋二階などの空や洞窟隙間の暗闇も。
[地形]…背景の上に重なる山・森・壁・毒沼・看板・柱・ベッド・机・じゅうたん・飾り床など。個別の認識不要なもの。例えば毒沼は同じ表示ならすべて同一の処理なのでこちらに。
[キャ]…キャラチップ。城・町・ほこら・扉・宝箱・タンス・移動の可能性あるキャラ。個別の認識を要するもの。例えば城・町は同じ表示でも個別に内容が異なる。

岩っぽいのを[キャ]に入れてる理由は“喋る岩”を登場させるから。扉を[地形]でなく[キャ]に入れてるのは開けた後その扉だけを消さないといけないから。

[イベ]…イベント入力。[キャ]で置いたものに対し、イベントの種類とIDを割り振るもの。マップ切替・宝箱や人の識別・タイルごとの難易度設定に使います。詳細は後述。

操作 選択したチップで埋める、置換する、入力したマップデータの保存、読込などを行います。

[全埋]…現在選択中のチップで編集画面内全域を埋めます。SHIFTキー押しながら→マップ全域に。
[空埋]…現在選択中のチップで編集画面内の未入力部分を埋めます。SHIFTキー押しながら→マップ全域に。
[置換]…左隅に表示された≫置換に従い、編集画面内を置換します。置換元→置換先の順番で選択し、左隅の置換関係を作ってください。SHIFTキー押しながら→マップ全域に。
[Load]…保存したマップデータを読み込みます。
[Save]…マップデータを保存します。
[chEv]…チェックイベントCheckEventを略したつもり。マップ内に入力したイベントとIDをリスト出力します。
ナビ マウスポインタを重ねたタイルの座標・入力内容の表示・編集画面の現在位置をナビゲーションします。

背:[背景]、地:[地形]、キャ:[キャ]、イとID:[イベ]の内容が表示されます。
全体マップ上の水色の枠は現在編集画面上に表示されている部分を表します。
編集画面 実際にタイルを並べマップ入力作業を行う場所です。マウスでのポイント場所には赤枠が表示されます。また、16x14タイルの枠←スーファミ相当が表示されます。
※編集できる最大面積は512x256タイル。上下左右に迷路を伸ばして端に到達しないよう中央から描けばOKです。データがある長方形部分だけをトリミングして保存、読込を行います。

「チップ置く」…マウス左クリックで現在選択中のチップを置きます。置けるのはレイヤごとに1種類です。SHIFTキー押しながら→水平・垂直に限定。
「チップ消す」…チップ選択各レイヤ末尾(一番右下)のチップを置くことで削除できます。SHIFTキー押しながら→水平・垂直に限定。
「マップ移動」…キーボードの矢印キー上下左右、または、マウスホイールでマップがスクロールします。SHIFTキー押しながら→水平方向にスクロール。

素人マップの作り方

イベント入力について

マップエディタとはRPG本体のプログラムと表裏一体。このマップエディタがどのような設計思想でデータを作るのか、RPG側のプログラムをどう構築しようとしてるのか、その概念を最初に。

[イベ]タブに切り替えた際のチップ選択部がこちら。【メモ】と書いた部分が見えます。

自作マップエディタ説明図

イベントとして0~6番の7つのイベント種を準備しました。

【メモ】部分にありますが、イベント0番を音有りマップ切替、イベント1番を音無しマップ切替、イベント2番を会話対象、イベント3番に敵の難易度を記録することにしました。

イベントの管理方法
イベント0番
音有りマップ切替
城・町の出入り、階段に設定。
まず、内部管理として城1を100番、中庭を101番、中庭隅の階段上の部屋を102番、中庭中央の階段下の部屋を103番と自分自身で名前を付けます。←RPG側のプログラムでクラス管理することになる情報。同様に、町1を200番、入口広場を201番、…。
城1の中庭101番のマップを作る際に、ワールドマップへ戻るタイルのID=100番、隅の登り階段のID=102番、中央の下り階段のID=103番と入力します。
RPG側のプログラムにイベント0番の数だけ遷移先を記録する配列を作り、そこにイベント名に対応する行き先IDと行き先マップでの座標を羅列しておけば、マップ遷移のプログラムが割と簡単に作れます。入り口が複数あるマップも対応可。
自分で書くのもなんだが、すごくわかりにくい説明…。
イベント1番
音無しマップ切替
ダンジョン内部などで見えない先にあるマップへ移動する場合に設定。
使い方は上記イベント0番と同じ。
イベント2番
会話キャラの識別
宝箱・タンス・人など話す・調べる対象に設定します。たくさんある場合、Ctrlキー押しながら→ID番号が更新されていきます。
人、動物など移動するキャラに設定されたものはその座標が初期値。RPG側で読み込む際にこのイベント2番はそのキャラに内包される情報として扱います。
イベント0番のとこで書いた城・町の識別番号ふりならどのマップに居るかは判別可能なので、例えば、城内の人物は0番~、町内の人物も0番~の番号ふりでOKと思います。ゲーム全体での通し番号でもいいけど数的に厳しいかと。
イベント3番
敵の難易度
敵の難易度を設定します。侵入可能なタイルすべてに設定。イベント3番だけは入力したIDの数値が編集画面上に小さく表示されます。
マップデータの容量削減のため、空白の場合はID=0とします。※つまり、難易度0は敵にエンカウントしない仕様にしないといけない。IDは好きなよう設定し、それを以ってRPG側のプログラムで敵の難易度を決めることになります。例えば255なら最強ボス100%エンカウントとか。

【制限】このマップエディタは1タイルにイベント種1つしか置けない仕様なので、もしワールドマップ上でアイテムが落ちてるタイル(つまりイベント2番が設定されたタイル)を作ると、そこはエンカウントしない場所となります。広大な面積全部にやくそうが落ちてるマップは作らないだろうし、エンカウントしないタイルが1つ孤立してたとしてもプレイヤは気付かない筈なのでこうしました。
イベント4番以降 リザーブです。現状は使用を想定していません。
必要あれば好きに定義していただければ。旅の扉などのアニメ付き遷移とか。

この設計思想でできた現在のRPG状況

上記の設計思想で進めた現段階の状態がコレ。お城の中を探索してみて下さい。

ワールドマップを作る場合

このマップエディタが編集できる最大面積は512x256タイル。プレイヤの負担を考慮したドラクエが256x256とのことなので。

それでも広大なマップをこの小さな編集画面で入力するのは結構つらいと思うので、補助ツールを作成しました。描いた白黒画像を食わせて初期マップデータを出力させるツールです。

城内・ダンジョンマップを作る場合

基本的には背景チップを並べてから地形・キャラチップを並べていくだけですが、キャラを置いたタイルに対するイベント入力がワールドマップより格段に多く。

[chEv]ボタンを駆使してID被りが無いよう、そのIDの遷移先マップの座標、発言セリフを自分でメモりながら入力していくことになります。

嫌らしいのはイベントIDを割り振った後にマップを左や上に伸ばしてしまう場合。左上が原点なのでせっかくメモった座標がずれてしまいます→伸ばすなら右下方向へ。

マップデータの出力フォーマット

出力されるデータのフォーマットはこう。

0,255,0,255,map No:,水平:256タイル、垂直:256タイル
mapd[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__,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__,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__,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__,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__,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__,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__,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__,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__,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__,0__,0__,0__,0__,0__,0__,0__';
mapd[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__,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__,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__,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__,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__,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__,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__,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__,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__,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__,0__,0__,0__,0__,0__,0__';

…

mapd[239]='0__,0__,0__,0__,0__,0__,4_21_,4_21_,4_5_,4_5_,4_5_,4_5_,4_5_,4_9_,4_9_,4_5_,4__,4__,4__,4__,4__,4__,4__,4__,4_5_,4_5_,4_5_,4_5_,4_9_,4_9_,4_21_,4_21_,4_21_,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,3__3-25,3__3-25,3_20_,3_20_,3_4_2-8,3_20_,3_20_,3__3-1,3_20_,3_20_,3_20_,3_20_,3_20_,3_8_3-1,3_8_3-1,3_8_3-1,3_20_,3_20_,3_8_3-1,3__3-1,3_20_,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_20_,3_20_,3_20_,3_20_,3_20_,3_20_,3_20_,3__3-1,3_4_3-1,3_4_3-1,3_4_3-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__,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__,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__,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__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,3__,3__,3__,3__,0__,0__,3__,3__,3__,3__,3__,3__,3__,3__,3__,3__,3__,3__,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__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__';
mapd[240]='0__,0__,0__,0__,0__,0__,4_21_,4_21_,4_5_,4_5_,4_5_,4_5_,4_9_,4_21_,4_21_,4_9_,4_9_,4__,4__,4__,4__,4__,4_5_,4_5_,4_5_,4_5_,4_5_,4_5_,4_5_,4_5_,4_9_,4_9_,4_21_,4_21_,4_21_,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,3__3-25,3__3-25,3_20_,3_20_,3_20_,3_74_0-1,3_8_3-1,3__3-1,3_20_,3_20_,3_20_,3_20_,3_20_,3_8_3-1,3_8_3-1,3_20_,3_8_3-1,3_8_3-1,3_20_,3_20_,3_8_3-2,3_20_,3_20_,3_20_,3_20_,3_20_,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3_8_3-2,3__3-1,3__3-1,3_4_3-1,3_4_3-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__,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__,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__,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__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,3__,3__,3__,3__,0__,0__,3__,3__,3__,3__,3__,3__,3__,3__,3__,3__,3__,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__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__,0__';

…

JavaScriptのソースとして移せるよう配列に入力する形で出力されます。単なるカンマ区切りでの出力と選択できるよう改良予定ではありますが。

1行目はそのマップに対するメモ→[開始x座標],[最終x座標],[開始y座標],[最終y座標],[マップNoメモ用],[マップのタイル数表記]。

2行目以降は1行づつmapd[y座標]=’………(水平1列のデータ)………’が順番に連なります。

RPG側のプログラムで必要となる、いくつ目のデータを取り出すとかそーいう作業は以下の自作関数を多用します。ご自身のマップデータへ変換する際のツール向けにも。

仕様が固まらずRPG側とマップエディタ製作が同時進行となってしまう素人プログラマーの所業。

とりあえずこれで何とかドラクエ型のRPGに耐えるマップデータが作れると思ってんだが、いかんせんRPG側がまだ完成しなくてな。

こんなマップデータだとこんなケースに対応できないよとか予見できる玄人のお方、是非ダメ出しお願いいたします。

コメント

タイトルとURLをコピーしました