【プチコン講座】マップエディタで作ったマップを読み込んで表示しよう
こんにちは。継続の錬金術士なおキーヌです。
ブログ毎日更新は132日目になります。
前回「【プチコン講座】GOTOを捨ててループと関数でかかって来いよ!」でGOTOの危険性と関数の重要性をわかっていただけたと思います。
第2、第3回と連続でプチコンのRPG作りの話じゃなくなったので第4回からはちゃんとRPGを作る話をしていきましょう。
せっかく関数の使い方を覚えたので、ちょっとレベルアップした関数の使い方も覚えつつ
現在は草原が全体に広がっているだけなので森やらなんやらを配置してゲーム画面らしくしてみようとおもいます。
SMILE BASICについて色々調べてみたところ、特定のフォーマットにしておけば
前回作ったようなマップ表示の関数を使わずとも「BGLOAD」という命令を使えば一発で描写出来るようでした。
今回使うマップエディタの形式に沿ってマップ表示を作成していこうと思います。
それではプチコンでRPG作り第4回目を始めましょう。
マップエディタを使ってみよう
プチコン付属のマップチップエディタを使ってみたのですが、思ったよりも使いづらかったので投稿プログラムの
「マップエディタさん v1.07」を活用させていただきました。
マップエディタさん v1.07
作者:スーさん
「マップエディタさん v1.07」の使い方は上記のまとめwikiの方に詳しく載っているのでそちらを参照してください。
マップレイヤーは以下のような状態になっています。
特にプログラム的なきまりではなく、今回私が作っていくRPGの形なので好きなようにして構いませんが
この形で説明していくのでこのチュートリアルに沿って習っていく人は真似てください。
数値が高いほど上に重なっています。
- 0 => 最下層レイヤー……地面などを置く場所
- 1 => 1層目レイヤー……壁や机などの不動な障害物を置く場所
- 2 => 2層目レイヤー……予備
- 3 => 3層目レイヤー……予備
- EV => イベントレイヤー……NPCや宝箱等の動いたり変化したりするモノを置く場所
作っていくRPGは1画面RPGなので、一旦こんな感じで大丈夫だと思います。
プレイヤーが移動出来たり出来なかったりする判定(衝突判定)にマップ配列を見るので、
判定に使うかもしれないレイヤー2とレイヤー3を予備として空けておきます。
判定だけ別配列にした方が良いかもしれませんが、ちょっとまだ先が分からないので一旦これで行きます。
私は以下のような感じのマップを作りました。
レイヤー0に草原のマップチップを敷きつめて、レイヤー1に木と階段を付けました。
マップエディタ中にプチコンBIGやプチコン3号だとXボタンを押せばメニューが表示されるので、DAT形式で出力してください。
DATA文やMP形式ではないので気を付けてください。
もちろん、この2つもお好みで大丈夫です。
今回私はDAT形式を読み込んで処理したかったのでDAT形式にしました。
作ったマップを保存して読み込んでみる
DATファイルを「TEST」という名前にして保存をしたら、今度はそれを読み込んでみましょう。
マップエディタ作者のスーさんが読み込みの手順をまとめていてくれましたのでそちらを流用させてもらいます。
# 変数定義
VAR I # 汎用変数
VAR OX = 0, OY = 0 # BG読み込みのオフセット
VAR SZ, MW, MH # チップサイズ、マップ幅、マップ高さ
DIM MAP[0] # マップレイヤー4枚+イベントレイヤー分
VAR BGW = CEIL(400/SZ), BGH = CEIL(240/SZ) # BG読み込み準備
# マップデータ準備
SZ = 16 # チップサイズ
LOAD "DAT:TEST", MAP, 0 # マップデータのロード
MW = SHIFT(MAP) # 読み込んだデータ配列の0個目を配列から切り離して取得(1638415という数字が入ってる)
MH = MW AND &HFFFF : MW = MW >> 16 AND &HFFFF # 取り出したデータからシフト演算やらビット演算をする
# マップデータ描写
FOR I=0 TO 3
BGSCREEN I, BGW, BGH, SZ # 1画面分のBG
BGLOAD I, -OX, -OY - I * MH, MW, MH * ( I + 1), MAP # マップ描写
NEXT
けっこう長いコードになっちゃいましたが、やってることは結構単純です。
1つずつ見ていきましょう。
変数定義
今回使う変数の定義ですね。
何に使うかはコメントを打っているので見てください。
プチコンのコメントはカンマ(’)ですが、PCだとBASICのコードをキレイに表示する機能をつけていないので
#になっていますが気にせずコメントアウトしているとおもっていてください。
VARとDIMですが、どちらも変数の定義なので同じようなものです。
しかしVARは普通の変数でDIMは配列と分けておいた方が見やすくて良いでしょう。
マップデータ準備
まずチップサイズ変数に16を代入しています。
プチコン3号などの場合は8x8らしいのでここでは16ではなく8を入れてみると良いと思います。
私はプチコンBIGなので16にしています。
次に、マップエディタで作成した「TEST.DAT」というファイルをLOAD命令で読み込みます。
LOAD ファイル名, 読み込んだデータを格納する配列, ダイアログを出すかどうか
ダイアログはセーブしますか?とかロードしますか?とか画面が出るかどうかの設定で
0にすると表示されずそのままロードされます。
ロードされたデータは指定した配列、今回はMAP配列にデータがはいります。
そしてデータを入れた配列の0番目にはマップのサイズ情報が入っています。
マップサイズの情報はマップを表示する関数に渡すときに邪魔になるので、
SHIFT関数を使って配列の0番目を切り取って変数に入れます。
コメントにも書いていますが、0番目のデータを表示してみると「1638415」という数字が入っています。
初見では何の数字かよくわかりませんね。
この数値ビット演算すると縦幅の「15」、シフト演算をしてからビット演算をすると横幅の「25」という数字が取り出せます。
ここは説明してもわかり辛いとおもうので省略します。
私もTwitterで助言をもらいながら2時間ほど悩みました。
今はこうやったらマップの縦横サイズをとりだせるんだなとおもっていてくれればOKです。
スーさんのマップエディタを使っていればここの演算は変わることはないので大丈夫です。
準備完了したのでマップデータを画面に表示してみよう
ついに作ったマップデータを表示する準備が出来ました。
前々回で作ったマップ表示をする関数は今回使いません。
私も後から知ったのですが「BGLOAD」という命令がSMILE BASIC側で用意されていて、
それを使えば作ったマップ表示関数のようにマップチップを1つずつ描写してくれます。
なんて無駄なことをさせてくれたんだ!
と思うかもしれませんが結局やっていることは同じです。
あの関数を作ったからこそ、このBGLOADが何をしているのかが良く理解できると思います。
実行してマップエディタで作ったまま表示されているかみてみよう
コードが打ち終わったらダイレクトモードに戻ってRUNで実行してみましょう。
ちゃんとマップが表示できたでしょうか?
もしLOADでエラーが出た場合は保存したマップの場所がまちがっていると思います。
今作っているプログラムと同じフォルダにいれておきましょう。
──BGLOAD関数を見つけてきゅうきょ目次を削除しました。
本当はマップ描写の関数を改良しようかなとおもったのですがBGLOADあればいらないなとなって
2項目だけになってしまったので目次は消しました。
それと、jsやphp等の厳密じゃなくてもうごいてくれるWeb系の言語を触ってきた人間からすると、
BASICのような2進数を意識する言語を触るとプログラマとして未熟なのがすごく体感できます。
今回、スーさんのマップエディタで作ったデータを読み込んで処理する時に、
ビットシフトやら16進数のビットがヘッダに必要やら色々やらなきゃいけないのは本当に勉強になりました。
Webだとファイルをロードしてもヘッダ周りは基本的に気にしなくても大丈夫なのでいい刺激になります。
1日ですんなり解決できたのはネットワーク系の勉強もある程度やっていたのと
何度かC++でゲームを作ろうとしてたことがあったからですね。
SmileBasicはやればやるほどなんか楽しくなってきました。
プチコン4が楽しみですね。
最後に完成版ソースコードを載せておきます。
それでは。
ACLS
# 変数定義
VAR I # 汎用変数
VAR OX = 0, OY = 0 # BG読み込みのオフセット
VAR SZ, MW, MH # チップサイズ、マップ幅、マップ高さ
DIM MAP[0] # マップレイヤー4枚+イベントレイヤー分
VAR BGW = CEIL(400/SZ), BGH = CEIL(240/SZ) # BG読み込み準備
# マップデータ準備
SZ = 16 # チップサイズ
LOAD "DAT:TEST", MAP, 0 # マップデータのロード
MW = SHIFT(MAP) # 読み込んだデータ配列の0個目を配列から切り離して取得(1638415という数字が入ってる)
MH = MW AND &HFFFF : MW = MW >> 16 AND &HFFFF # 取り出したデータからシフト演算やらビット演算をする
# マップデータ描写
FOR I=0 TO 3
BGSCREEN I, BGW, BGH, SZ # 1画面分のBG
BGLOAD I, -OX, -OY - I * MH, MW, MH * ( I + 1), MAP # マップ描写
NEXT