過去ブログの転載です。
イベント命令の簡略化についてやってみます。ハノイの塔を作ってみましょう。ハノイの塔ってなんだって?? ごめんなさい割愛します。パズルですよ。ウィキペディアをお読み下さい。
いわゆる古典的なパズルですが、RPGツクールでさあ作ろうと思ってもどこから手を付けていいかなかなか分かりづらいものです。
そこで、どのように作ろうか、大まかな手順をまず考えます。
① 枚数を決める
② 準備する
③ ハノイの塔を画面に表示する
④ クリアしていたら、終了する
⑤ クリアしていなかったら、板を移動して、③に戻る
↑こういった感じになるでしょうね。どうしても、思い付きでイベント命令を組み始めると複雑化しやすいので、わけがわからなくなって挫折してしまう危険があるのです。ここではこうやってまず纏めておき、相互変換モジュールを使って簡潔にシステムを書くことを目指しましょう。
画像素材はここにあります↓
プログラム本体は、次のようになります。
#include "ハノイの塔.as"
質問 // 枚数をプレイヤーに入力してもらう
初期化 // 変数の初期化
cy
表示 // 板を表示
終了判定 // 残り回数が0になったら終了
移動 // 板を移動させる
cyendsend
↑ cy ~ cyend は繰り返しの処理です。上で書いた手順そのものではありませんか。そうです、そのものです。こうやって、個々の処理をまとめていくことにより、簡潔にシステムを記述することができ、なおかつバグが発生したときにどの命令が原因なのかというのを把握しやすくなります。
個々の命令がどうなっているかというと、こうなっています。
『ハノイの塔.as』
#include "rpgfunc.as"
goto *@f
#deffunc 質問
msg "枚数は?(1~13)"
number 2, 1
co 1, 1, 0, 0, 0
msg "それはダメだよ……"
hangup
coend
co 1, 1, 0, 14, 1
msg "それはダメだよ……"
hangup
coend
return#deffunc 初期化
varsel 2 : var 0, 0, 1, 0
varsel 3 : var 0, 1, 1, 0
varsel 3 : var 1, 0, 20, 0
cy
varsel 2 : var 3, 0, 2, 0
varsel_var 3 : var 0, 0, 0, 0
varsel 3 : var 2, 0, 1, 0
co 1, 3, 0, 20, 0
varsel 2 : var 2, 0, 1, 0
cybreak
coend
cyend
pic 1, "土台", , , , , , 1
return#deffunc 表示
varsel 4, 6 : var 0, 0, 205, 0
varsel 3 : var 0, 1, 1, 0
varsel 3 : var 1, 0, 20, 0
cy
varsel 7 : var 0, 2, 3, 0
varsel 7 : var 3, 0, 105, 0
varsel 7 : var 1, 0, 55, 0
varsel 8 : var 0, 2, 3, 0
varsel 8 : var 1, 0, 4, 0
varsel_var 8 : var 2, 0, 10, 0
varsel 8 : var 0, 2, 8, 0
repeat 13, 1
co 1, 3, 0, 20 + cnt, 0
pic cnt + 1, "板" + cnt, 1, 7, 8
coend
loop
varsel 3 : var 2, 0, 1, 0
co 1, 3, 0, 20, 0
cybreak
coend
cyend
pause 3
return#deffunc 終了判定
co 1, 2, 0, 0, 0
msgop 1, 0, 0, 1
msg "【終了】"
msgop 0, 2, 0, 1
repeat 14, 1
picdel cnt
loop
hangup
coend
varsel 2 : var 2, 0, 1, 0
return#deffunc 移動
varsel 7 : var 0, 1, 2, 0
varsel 7 : var 5, 0, 2, 0
co 1, 7, 0, 0, 0
rem "【回数が奇数の場合】"
varsel 21 : var 1, 0, 1, 0
varsel 21 : var 5, 0, 3, 0
coelse
rem "【回数が偶数の場合】"
varsel 3 : var 0, 0, 21, 0
varsel 7 : var 0, 0, -1, 0
cy
varsel 8 : var 0, 2, 3, 0
co 1, 7, 1, 8, 5
co 1, 7, 0, -1, 0
varsel 7 : var 0, 1, 8, 0
coelse
varsel_var 3 : var 0, 1, 7, 0
varsel_var 3 : var 1, 1, 8, 0
varsel_var 3 : var 2, 0, 3, 0
varsel_var 3 : var 3, 0, -1, 0
cybreak
coend
coend
varsel 3 : var 1, 0, 1, 0
cyend
coend
return*@
#deffuncから始まるブロックごとに処理を書いています。こうすると一つ一つは小さく纏められるので、考えやすくもなるはずです。
拡張子「.as」にするとこれはヘッダファイルと呼ばれるものになります。『ハノイの塔.as』というのは、『ハノイの塔.hsp』のヘッダファイルです。分かりやすいように、同名にして拡張子だけ変えています。「.as」の方に個々の命令をそれぞれ格納しておき、本体を「.hsp」の方だけに書けば、非常に簡潔にまとまって見やすいものになると思います。おかしなことが起こったら、デバッグの際にメッセージか何かを本体の方に入れればどの命令がおかしいのか確認できますねぇ。
「.as」を取り込む命令が、「#include」になります。「.hsp」の先頭に書いてありますね。その名の通り、ソースファイルを「含む」のです。「.as」のソースすべてを「#include "ハノイの塔.as"」の一行で済ますわけですね。
「.hsp」の方を簡潔にするために、「.as」の先頭に「#include "rpgfunc.as"」と書いてあります。もちろん、「.hsp」の方で書いても構いません。
このことからお分かり頂けますでしょうが、「rpgfunc.as」もまたヘッダファイルです。これをインクルードすることによって、「msg」とか「send」とかが使えるようになるわけです。
「goto *@f」は、次の「*@」がある行まで飛ぶ、という命令です。
「goto *@f」から「*@」の間に、個々の命令の内容を記述していきます。
命令を作るには、「#deffunc 命令名」から「return」までの間に内容を記述します。命令名には日本語が使えます。上の例でも使っていますが……命令名には引用符は付けません。
命令の内容はツクールの方で作成し、それを相互変換を用いてHSPにして「.as」に格納していく、といったことをすると良いでしょう。動作確認をするときは「.hsp」の方で実行してすべての命令をクリップボードにコピーし、ツクールに貼り付けることにします。修正する場合はHSPの方を手直しし(時々相互変換しながら)、再度動作確認をするときはツクールに前回貼り付けた分をすべて削除して、新しく貼り付ければそれで済みます。
↑ハノイの塔の個々の命令で何をやっているのかは割愛しています……単に、ハノイの塔をやっているだけです^^;「.hsp」を開いてF5を押してツクールに貼り付ければ、ちゃんと動作するはずです。
次の変数を使用しています。
変数 1番:枚数
変数 2番:残り回数
変数 3番:枚数一時
変数 4番:柱1 y座標
変数 5番:柱2 y座標
変数 6番:柱3 y座標
変数 7番:一時1
変数 8番:一時2
変数21番:位置(1枚目)
変数22番:位置(2枚目)
変数23番:位置(3枚目)
変数24番:位置(4枚目)
変数25番:位置(5枚目)
変数26番:位置(6枚目)
変数27番:位置(7枚目)
変数28番:位置(8枚目)
変数29番:位置(9枚目)
変数30番:位置(10枚目)
変数31番:位置(11枚目)
変数32番:位置(12枚目)
変数33番:位置(13枚目)
このように命令を簡略化することにより、個々の命令そのものはどのようにして動いているのか知らなくても、「.hsp」だけを見れば大体こういう風に動いているのかと分かるというメリットもあります。
だんだんオブジェクト指向な感じになってきましたねええ。