【プチコン4講座】RPG用のマップデータを作成しよう
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は148日目になります。
プチコン4になって命令が結構変わってしまったので、
今まで作っていたプチコンRPG講座がそのまま使えないようになってしまいました。
しかも初っ端からマップデータがないので進められないという状況に陥りました。
そのうち有志の方がマップエディタを作ってくださると思うのですが、待っているのもあれなのでマップを自作してしまいましょう。
そして今まで書いたプチコンBIGの記事をプチコン4に流用できるように外部ファイルにしてしまおうというものです。
プチコン4の命令の詳しい詳細は割愛することが多いので、
わからなくなったら命令を打ち込んでF1キーを押すか公式リファレンスをみてください。
それではプチコン4でRPG作り第1回目を始めましょう。
- マップチップを表示してみよう
- マップ配列を作って画面全体にマップチップを敷き詰めてみよう
- マップデータを外部ファイルに切り分ける方法を考えてみよう
- 外部ファイルを読み込んでマップをロードして表示してみよう
マップチップを表示してみよう
プチコン3号&BIG (以下ver3系列)で使えていたBG命令がなくなって、
テキストスクリーンという概念に置き換わっています。
BGSCREENという便利な命令がなくなってしまったので自分でマップ描写の処理を作らなければいけません。
ひとまずはマップチップを表示してみましょう。
ダイレクトモードで以下のコードを打ち込んでください。
TPRINT 0, CHR$(&HE8CA)
どうでしょうか?
左上にマップチップが表示されたと思います。
これを全画面にやるわけですね。
単純に考えたらFORで繰り返して表示したいところです。
一回試しにやってみましょう。
次もダイレクトモードで大丈夫です。
VAR I=0 : FOR I=0 TO 10 TPRINT 0, CHR$(&HE8CA) NEXT
やっていることは
- 変数の宣言
- FORの開始
- TPRINTでマップチップ表示
- 10回繰り返す
ですね。
実行してみるとどうでしょうか?
理想的なマップチップの並び方になりましたか?
……違いますね。
縦に並んでしまっています。
TPRINTはその名の通りPRINTと似たような機能をします。
なのでマップを表示するためのものではなくただ単に表示するだけの命令ですね。
じゃあどうするのかというと、「TPUT」を使います。
TPUTで好きなところにマップチップを置いてみる
TPUT命令はTPRINTと違って座標の指定をすることができます。
ためしにてきとうな位置にマップチップを置いてみましょう。
TPUT 0, 100, 100, CHR$(&HE8CA)
どうでしょうか?
エラーが出たと思います。
過去にプチコンをやったことがある人であれば数値1=マップチップのサイズ
となっているからです。
X座標=0・Y座標=0だと左上ですね。
X座標=1・Y座標=0だとマップチップのサイズ分X座標をずらしてみると、
マップチップ1つ分ずれるのがわかると思います。
文字だけではわかりづらいと思うので実際に打ち込んで体感してみましょう。
試しにX座標1と3のものを配置してみます。
そのまえに画面がごちゃごちゃしてきたら
ACLS
で画面をクリアしましょう。
それではマップチップを置いてみます。
TPUT 0, 1, 0, CHR$($HE8CA)
TPUT 0, 3, 0, CHR$(&HE8CA)
ダイレクトモードで1つずつ実行してもいいですし、:で区切っても大丈夫です。
数値を1ふやすと1つ感覚を空けて表示されているのがわかるでしょうか?
スプライト(キャラクターやモンスター等)は1ドットずつ座標を指定できますが、
マップチップは基本的にチップサイズごとに動きます。
今後ゲームを作る上ではこの仕様に気をつけてください。
マップ配列を作って画面全体にマップチップを敷き詰めてみよう
マップチップの配置の仕方がわかったところで、FOR命令を使って画面全体に敷き詰めてみましょう。
その前に、マップの配列を作らなければいけません。
マップの配列とは、その名の通りマップのデータを1つにまとめたものです。
FORで配列1つずつアクセスして、中の数値によって表示するマップチップを変更するといった感じです。
それでは試しにEDITモードでマップデータを打ち込んでみましょう。
多く見えますが、やっていることはすごく単純です。
' 配列の宣言
DIM MAPDATA[] = [\
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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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\
]
プチコン4からは改行して続けてコードをかけるようになりました。
その時は必ず行末に\マークもしくは\(バックスラッシュ)をつけてください。
当記事ではみる端末によっては¥マークかバックスラッシュどっちかに見えると思います。
プチコンのエディタではちゃんとバックスラッシュになっています。
話をマップデータに戻すと、プログラミング初心者からすると「なんだこれはたまげたなぁ……」
ってなってしまうかもしれませんが、これがRPGのマップデータになります。
1が木で0が地面としてみればマップに見えてきませか?
それではこの配列を使ってマップチップを画面全体に敷き詰めてみましょう。
配列をFORで回してマップチップを敷き詰める
最初に習ったTPUTとこの配列とFORを組み合わせてマップチップを全画面に描写してみましょう。
次に書くコードは配列を宣言した後に書いてください。
ACLS
' 変数の定義
VAR G_I = 0
VAR G_J = 0
VAR G_BGW = 25
VAR G_BGH = 15
' マップチップ配列を描写
FOR G_J = 0 TO G_BGH-1
FOR G_I = 0 TO G_BGW-1
' ローカル変数CPに計算した値を入れる
VAR CP = G_I + ( G_J * G_BGW )
' CASE文でMAPDATA[CP]の内容に応じて処理を切り替える
CASE MAPDATA[CP]
' 0のとき
WHEN 0:
' 地面を表示
TPUT 0, G_I, G_J, CHR$(&HE8C9)
' 1のとき
WHEN 1:
' 木を表示
TPUT 0, G_I, G_J, CHR$(&HE8CA)
ENDCASE
NEXT
NEXT
コメントを読んでもらえたら何をしているのかわかると思いますが、軽く説明しておきます。
まずループに使う変数とマップの横幅と縦幅の変数を明示的に定義しています。
実はこの変数定義、以下のように1行でかけます。
VAR G_I = 0, G_J = 0, G_BGW = 25, G_BGH = 15
しかし今回は見易さ重視でやっているので4行使っています。
変数の説明をすると
- G_I => 内側のFORに使う変数
- G_J => 外側のFORに使う変数
- G_BGW => マップチップサイズ基準での画面の横幅
- G_BGH => マップチップサイズ基準での画面の縦幅
これらを使ってマップチップを描写します。
FORの中にFORを使う場合は意外とゲーム作り以外ではやったことはありませんが、
二次元配列を扱う時は結構使えるテクニックなので覚えておいて損はないでしょう。
外側のFORは内側のFORが全部終わってからやっと1ループすることとなります。
内側のFORは1回回るごとにX座標を1つずらしてマップチップを描写していきます。
そして内側のFORが25(0~24)回回ったら外側のFORの数値が1つ増えるので、
その時にY座標をずらしてまた内側のFORがX座標を0からスタートします。
イメージ的にはノートに横線を左から右にペンを引っ張って端っこまでいったら、
次の行の一番左からまた右にペンを引っ張っていく感じです。
試しに、FORのところで「WAIT 1」の命令を挟んでみるとよくわかると思います。
WAITを入れるところはCASE文の終わり「ENDCASE」の下に入れてみてください。
そして実行すると、1つずつマップチップが描写されるのがわかると思います。
これで画面全体にマップチップが描写されたと思います。
マップデータを外部ファイルに切り分ける方法を考えてみよう
1ステージだけだとソースコードにマップを置いててもいいですが、
ステージが増えてくるとその分ソースコードがマップだらけになってしまいます。
このマップデータは外部ファイルとして切り分けたいですね。
特殊なデータ型にしてもいいですし、プチコンで開けるデータのままでもいいです。
とにかく外部ファイルを読み込んで配列にマップデータを読み込めたら手段は問いません。
有志の方がマップエディタを作ってくれるまでは一旦、マップ配列をDATファイルとして自分で保存してマップデータにしてみましょう。
作業スロットを切り替えてマップデータを保存する
プチコンのエディットモードにはスロットと言われるいわゆる別ページを設けられています。
Switchのコントローラーで言えば「ー」ボタンを押してメニューを表示し、右スティックでマウスカーソルを動かし「Ctrl」のところまでいって右スティックを押し込むと画面が切り替わります。
そしてEDIT0~3というボタンがあるのでEDIT1のところを押してみるとページが切り替わります。
USBキーボードを持っている人は「Ctrl+1~4」で切り替えられます。
それではEDIT1スロットにマップデータを持ってきましょう。
DIM MAPDATA[] = [25,15,\
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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,\
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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\
]
SAVEV "DAT:MAP001",MAPDATA
このように打ち込んでください。
さっきのマップデータに25,15を先頭に追加しました。
これはマップの横幅と縦幅の情報ですね。
こうやってマップデータに組み込んでおくとマップサイズをいちいちメインプログラムに書く必要は無くなります。
実際、描写する時に邪魔になるので先頭の2つは取り除いてから描写するという処理にします。
そして最後の命令にある「SAVEV」
これはファイルの形式を指定して数値配列をDATファイルとして保存できます。
SAVEVの使い方の詳細はF1でヘルプを見てください。
それではこのスロットを実行してみましょう
ダイレクトモードで
RUN 1
と打ち込んでみてください。
これはスロット1を実行する命令です。
ただのRUNだけだとスロット0が実行されてしまいます。
実行すると保存するかどうか聞かれるので、保存してください。
これでマップデータファイルの作成ができました。
外部ファイルを読み込んでマップをロードして表示してみよう
先ほど保存したMAP001ファイルを読み込んでみましょう。
保存が「SAVEV」だったのに対し、読み込みは「LOADV」を使います。
早速読み込んでみましょう。
' 空配列宣言
DIM MAPDATA[]
PRINT LEN(MAPDATA)
MAPDATA = LOADV("DAT:MAP001")
PRINT LEN(MAPDATA)
LOADVにファイルの拡張子とファイル名を与えています。
これで成功すれば配列としてデータが返ってくるので最初に用意した空配列に入れてあげます。
入れる前と後で配列の数を表示する「LEN」命令をPRINTしているので
0
377
と表示されればちゃんと読み込めています。
読み込んだマップデータを使って画面をマップチップを敷き詰めよう
それでは最初に作ったマップデータ描写を使ってマップを表示してみましょう。
そのまえにまずは配列の先頭2つが横幅と縦幅なのでそれを取り出します。
それから最初に作ったマップ表示の処理を当てはめてください。
ACLS
' 変数宣言
VAR G_I = 0, G_J = 0, \
G_BGW = 0, G_BGH = 0
' 空配列宣言
DIM MAPDATA[]
' マップデータファイル読み込み
MAPDATA = LOADV("DAT:MAP001")
' マップデータ配列の先頭2つを取り出す
G_BGW = SHIFT(MAPDATA)
G_BGH = SHIFT(MAPDATA)
' マップチップ配列を描写
FOR G_J = 0 TO G_BGH-1
FOR G_I = 0 TO G_BGW-1
' ローカル変数CPに計算した値を入れる
VAR CP = G_I + ( G_J * G_BGW )
' CASE文でMAPDATA[CP]の内容に応じて処理を切り替える
CASE MAPDATA[CP]
' 0のとき
WHEN 0:
' 地面を表示
TPUT 0, G_I, G_J, CHR$(&HE8C9)
' 1のとき
WHEN 1:
' 木を表示
TPUT 0, G_I, G_J, CHR$(&HE8CA)
ENDCASE
NEXT
NEXT
これで最初と同じ感じでマップチップを描写できたと思います。
最初から結構やることが多くて疲れたと思います。
プログラミングは結構頭を使うのでチョコレートなどを食べて休憩を挟むとはかどりますよ。
次回はマップデータをプチコンBIG講座に対応できるように作り変えてみましょう。
それでは。