ウディタでシンプルなシミュレーションRPGのシステムづくりに挑んでみたので、その様子をメモとして残しておきます。使えそうな記述やアイディアがあれば、自由にお使いください。
筆者はこちらで紹介した作品・サイトの皆さまから学んでおります。
さてさて、SRPGというと移動処理が最初の関門でありキモですが、それをこなす前にやっておくとラクなことがあります。それだけでも結構な量ですので、今回と次回の2記事ぶんを準備にあててから、SRPG製作を本格的に行いたいと思います。
今回やるのは最低限のUI作り――いま選択中のマスがどこで、そのマスはどんなデータを持つ地形なのかを画面に表示する処理です。
完全にまっさらな空データ(デフォシステムなし)・1マス移動4方向の設定で作っていきます。
移動処理を作る前に必要な表示情報(UI)
こんなマップがあったとします。
UIの定義だとかよいUIはなんだといった話はさておいて、下の画像のようにSRPGならマウスカーソルが重なっている(選択中の)マスの位置や、そのマスのゲーム的な座標(位置)、そこが森なのか草むらなのかといった「マス情報の表示」が必要ですね。
マウス操作のSRPGだとすると、次の処理が必要になりそうです。
- マウスカーソルのあっている位置のゲーム中の位置(マス座標)を取得
- 選択中のマスにポインター(上図では赤い四角)を表示する
- マス情報(地形データ)を取得
ゲームがかたまってきたらこのコモンは大きく作り直すことになりますが、取得して表示する項目が増えるだけで(そのマスにいるユニットの能力とか)、骨子の動作は現段階とそう変わらないでしょう。
準備1.選択中のマスの情報を取得して表示するコモン
マス座標を取得し、ポインターを表示する
ウディタのデフォ状態だと画面解像度は320×240でタイルサイズは16です。
1画面にはタテ20マス&ヨコ15マスおさまりますので、 画面解像度/タイルサイズ=1画面におさまるマス数 という関係です。
ということは、マウスカーソルが X250,Y70にあるとき、マス目としてはX=250/16=15とY=70/16=4 にカーソルが合っているわけです。
そのへんを踏まえて、こんな並列処理のコモンを作ってみました。
「スクロールして画面外にもまだマップが広がっている」ケースではもうちょっと処理を足す必要がありますが(スクロール量に合わせたマス目の調整)、今回はこれでよいでしょう。
注意点としては、ポインター(赤い四角)のピクチャ番号がマイナスになることです。
ユニットをキャラチップ(マップイベント)で表現する場合、ポインターはキャラの下にある方が見栄えがいいのです。
・ピクチャ番号が100000(10万)未満なら文章や選択肢の下に表示
・ピクチャ番号が100000(10万)以上なら文章や選択肢の上に表示
・ピクチャ番号が-1~-99999なら、マップの上、かつ、イベントの下に表示
・ピクチャ番号が-10万以下なら、マップの下、かつ、遠景の上に表示
また、同じく見栄えの問題で、マウスカーソルが画面外にある時はポインターを消すようにしてあげるとよいでしょう。
画面外かどうかの判定を行う「┗マウス画面外?」のコモンはこんな感じ。
■変数操作: CSelf4[画面外?_Yes1] = 1 + 0
■条件分岐(変数): 【1】 Sys71:マウスX位置 が 0 以下 【2】 Sys71:マウスX位置 が 320 以上
-◇分岐: 【1】 [ Sys71:マウスX位置 が 0 以下 ]の場合↓
|■
-◇分岐: 【2】 [ Sys71:マウスX位置 が 320 以上 ]の場合↓
|■
-◇上記以外
|■条件分岐(変数): 【1】 Sys72:マウスY位置 が 0 以下 【2】 Sys72:マウスY位置 が 240 以上
|-◇分岐: 【1】 [ Sys72:マウスY位置 が 0 以下 ]の場合↓
| |■
|-◇分岐: 【2】 [ Sys72:マウスY位置 が 240 以上 ]の場合↓
| |■
|-◇上記以外
| |■変数操作: CSelf4[画面外?_Yes1] = 0 + 0
| |■
|◇分岐終了◇
|■
◇分岐終了◇
画面のハジの1ドットでも画面外扱いされますが、筆者が試した限りではこの形が画面外判定ではいちばん簡便です。
地形のデータベースを整備してタグ番号と紐づけする
森のチップにポインターが合っていたら、右上のマス情報でも「森」と名前が出る。水場なら水場、道なら道……と。人間が目で見れば一目瞭然ではありますが、ウディタのプログラムさんにわかっていただけるようには一工夫が必要です。
マップチップでは通行設定の他に「タイル番号」というものが00~99範囲で設定できますので、これを自作のユーザーベースと関連させるのがよいでしょう。
過去に足音関係のコモンにて説明したのとまったく同じ手順を踏みます。
今回の記事の場合は、草地は0番、道は1番、森は2番……という具合です。
上掲のコモンではすでに「選択中のマスのタグ番号からユーザーベースへ辿っていってその地形の表示名を拾ってくる」処理が仕込まれております。
よい感じですね。
右側はユニット(ウルファールさん)の下にポインターがあります。
準備2.地形ごとの消費移動力を設定する
SRPGは基本的には1マス移動するのに移動力を1使いますね。
歩兵なら山は通れなくても、飛行ユニットなら平地同様に消費移動力1で通過できてしまったり……という設定も、この段階で構想・設定を済ませておくと後が楽です。
消費移動設定は、さきほど作った「地形のユーザーベース」に項目を足していきます。
こんな感じですね。
「絶対に通れない」地形は99など極端な値を設定します。逆に、消費移動力は最低でも必ず1は必要です。
他にもユニット・クラスの移動タイプには「騎馬」や「ワープ」などいろいろ考えられます。必要に応じて設定していきましょう。
あとは先ほどの地形名の取得と同じ要領で、この消費移動力も取得できるようになりました。
準備3.操作系の大枠をつくる(操作受付フロー)
準備1.で並列処理コモンを作ってもらいました。
実際にはこれから「クリックがあった場合の反応」、「ユニットにポインターを合わせた際の移動範囲の表示(移動力計算)」と、マウス操作にかかわる処理がワンサカ増えていきます。
そのすべてを別々の並列処理としてしまうと死ぬ目に遭います。筆者は遭いました。
なので、できるだけ「1つの並列処理」が「必要なコモン」を「適切な順番に呼び出して処理する」フローを意識していくことがだいじなのだと思います。
1つの並列コモンで次のような順番に各種処理をするイメージでやっていきます。
- マウスカーソル位置から選択中のマスの座標を取得
- 取得の座標に対応するポインターや地形情報などを表示する
- マウスクリックに対応した各種操作
実際に書くとこんな感じ。
コモンのなかでループをかけているので、並列でなく、どこか別の処理からの呼び出しでも対応できるでしょう。
マス座標取得のコモンは、X座標とY座標の2変数を2行の文字列として返しています。やり方はこちらの記事に詳しいです。
また、準備1.のやり方だと、選択中のマスが変わらなくても1フレームおきに情報の取得と表示の更新を行っていたので、「前回表示したのと違うマスを選択した場合にだけ、表示更新を行う」ように流れを変えています。
クリック検知コモンの中はまだカラでよいでしょうし、それ以外のコモンは準備1.に詰め込んだものを各種分散させたものです。
下準備としてはこんなところでしょうか。
ちなみに、「┣2点間の距離を取得」は頻用の計算なので、たったの3行でもコモン化しておくとラクそうです。
■変数操作: CSelf10[X差] 絶対値= CSelf0[点AのX] – CSelf2[点BのX]
■変数操作: CSelf11[Y差] 絶対値= CSelf1[点AのY] – CSelf3[点BのY]
■変数操作: CSelf4[結果] = CSelf10[X差] + CSelf11[Y差]