【プチコン講座】RPGのイベントシステムの作り方

プチコン

プチコン RPG イベント

こんにちは。継続の錬金術士なおキーヌです。

ブログ毎日更新は137日目になります。

前回「【プチコン講座】グリッド移動の衝突判定を作ろう」レイヤー別でグリッドによる衝突判定を行いました。

だいぶゲームぽくなってきましたね。

プログラミングによるRPG制作は本番はここからです!

次にやることはイベントを配置しなければプレイヤーしかいないので面白くないですね。

またお話だけになりますが、少し複雑になってきますのでじっくりやって確実に完成を目指すべきです。

それではプチコンでRPG作り第9回目を始めましょう。

  1. イベントはどうやってマップに置くのかを考える
  2. 各イベントの情報をまとめたファイルを作る
  3. イベント用の配列構成をどうするか
  4. 各イベントのプログラムを考えてみよう
  5. RPGを作るな!RPGを作れ!

イベントはどうやってマップに置くのかを考える

イベントの見た目はプレイヤーと同じで基本はスプライトで表現してマップに配置します。

今まで作ってきた座標取得やグリッド移動などの関数はイベントも利用するので汎用性のあるものにしました。

しかしイベントは1つじゃなくて複数ありますよね。

1つ1つ同じ場所に書いていてはコードが長くなりすぎて見辛くなります。

なので外部ファイルに設定をまとめて読み込んでその情報を元にイベント用のスプライトを生成するというのが基本になります。

プチコンでは定義に便利なjsonは使えませんのでスプライト変数の余っているところをイベントNoとして割り当てて、
その数値をもとにデータをまとめた配列から取ってくるという方法が楽だと思います。

調べたらjsonパーサーを作ってくださっている方がいらっしゃったので自分のゲームを作るときに使おうと思います。

一旦、jsonを使わずにプチコンそのものの機能だけでどうやるかを覚えておいた方がいいと思いますし
私もこれを書いている時点でプチコン歴は1ヵ月にも満たない超絶初心者です。

データ構造を考えてみよう

まずイベントを作るにはどんなデータが必要かを洗い出してみましょう。

例えばモンスターイベントを作るためにはざっくりと以下のデータが必要になります。

  • イベントID
  • イベントタイプ
  • メッセージ内容
  • モンスターの各種情報

1つずつ見ていきましょう。

イベントIDとは

そのままですね。

この番号はユニーク(他とはかぶらない)な番号になるので基本的には連番にしていけばOKです。

結構これは重要な数値で、例えば前回やった衝突判定の時にこの数値を利用します。

イベントレイヤーのグリッドにイベントIDを記述しておけばそのグリッドにイベントがいるという判断ができるからです。

例えばAボタンを押されたときに向いている方向のグリッドのイベントレイヤーを調べると、1というイベントがあれば
そのイベント内容を引っ張ってくるといった感じですね。

なのでこのIDをかぶったものにしてしまうと別のイベントを呼び出してしまうことになります。

イベントタイプとは

イベントタイプはこれもそのままの意味で、モンスターなのか宝箱なのかメッセージを表示するだけの村人なのかという意味ですね。

イベントタイプ0番目は何もなし。

イベントタイプ1番目はメッセージの表示

イベントタイプ2番目はバトル開始

という具合にルールを決めてあげればそれぞれのイベントテンプレートに当てはめれば無駄な処理を書かなくても済むようになります。

イベントタイプはイベントIDと違って1つのイベントに1つのタイプを持たせるというのではなく、
イベント内容1つ1つにタイプを持たせるという意味です。

これはRPGツクールをやったことがある人なら理解しやすいと思います。

例えばモンスターでもボスだった場合メッセージを出して会話してから戦闘シーンに突入しますよね?

その場合例えば人間に化けていたモンスターに話しかけた場合以下のようになります。

  • イベントタイプ:メッセージ(俺は実はモンスターだったのだ!)
  • イベントタイプ:グラフィック変更(モンスターの姿に変更)
  • イベントタイプ:メッセージ(行くぞ勇者ども!)
  • バトル開始
  • イベントタイプ:メッセージ(グフッ!)
  • イベントタイプ:グラフィック変更(倒したのでグラフィックを消す)

内容はベタですが意味が分かりやすいと思います。

このイベントタイプが増えるたびに処理を書かなければいけませんが、一度書いてしまえば使いまわせるので楽ですね。

メッセージ内容

イベントに話しかけたとき、どんなセリフをしゃべるのかを記憶出来たら便利なのですが
スプライト用の変数は基本的に数値しか保存できないので文字を保持しておくのは難しいです。

なのでメッセージは文字列の配列を作ってしゃべらせたい内容を、
その配列から数値を使ってアクセスして取ってくるというやり方が基本になるのではないでしょうか。

そうするとメッセージを1つのファイルにまとめることができます。

しかし値をミスってしまうとそのキャラのセリフではないものを呼び出してしまうので気を付けましょう。

モンスターの各種情報

どのグラフィックにするかは、マップチップと同じで基本的にはグラフィックの番号さえ保存していれば
いつでもその番号で画像を呼び出せますね。

初期HPをいくらにするのか、攻撃力や防御力をどれぐらいにするのかも決めておきます。

各イベントの情報をまとめたファイルを作る

基本的にイベントデータは文字列を使わず数値で管理したほうがよいでしょう。

後から見たときこの数値なんだっけってなる可能性が高いので逐一コメントを書いておくべきですね。

PCでプログラミングするなら1つのファイルにまとめても見やすいのですが、
プチコンの場合はメインプログラムには情報を書かないほうが良いでしょう。

なので外部ファイルとして切り分けるのがベストです。

プチコンで読めるファイルで作る

一旦はプチコンで開けるデータにしておいたほうがあつかいやすくていいでしょう。

いきなり作ったデータを暗号化して読み込んで複合化してデータを引っ張り出すという方法は
初心者バイバイなのでまずはシンプルに変数や配列を使ってデータを作りましょう。

暗号化やバイナリ化は後からでも構いません。

専用ツールで作る

まだ調べていないのですがプチコン界隈は変態(誉め言葉)ともいえる人たちが多く、
え!?まじでプチコンでそのソフト作ったの!?すげぇ!

ってのがあふれていました。

今朝見つけたjsonパーサーもそうですね。

もしかするとエクセルもどきを作っている人がいて、
カンマ区切り(csvファイル)に書き出してくれるツールを作っている方もいるかもしれません。

それを使えばイベントデータ作りはかなり楽になりますね。

RPG作りに便利そうなツールを紹介する記事を作っても面白そうです。

イベント用の配列構成をどうするか

プレイヤーは一人なので配列にしなくてもいいですが、イベントはモンスターだけではなく宝箱や階段等複数あると思います。

そしてイベントデータも複数のデータを持っているので配列の配列(多次元配列)になるということです。

プチコンは多次元配列に対応しているのですが、個人的には極力多次元配列は使わないで行きたいところです。

プログラミングは使えるものは使って楽してナンボなのですがメモリの多い最近のPCであれば問題ないですが、
ゲーム機はメモリの量もPCに比べると小さいので、なるべく節約しておいた方がいいです。

マップがレイヤー分も含め1次元配列にしたように、イベント情報配列も1次元で実装できます。

ただ、マップと同じようにイベント毎に使うデータの数は統一しておかなければ、ポケモンのセレクトバグみたいな現象が発生します。

とりあえず文字でイベント情報を構築してみよう

実際は数値で管理したいのですが、わかりやすいように文字列でイベント情報を構築してみましょう。

次に書くようなコードはjson形式なので通常のプチコンでは自力で処理するかjsonパーサーを使うしかありません。

今回の講座では実際には使いませんが、イベントリストは以下のような感じになります。


{
  "event" :
  [
    {
      "comment" :"たからばこ1", // 使わない 自分が何かわかる目印
      "id":"0001", // イベントID
      "move": "static", // 動き方タイプ static => 動かない
      "collision":"ng", // 重なることが出来るかどうか ngなので×
      "image": "actor01.png,", // スプライトの画像
      "json" : "/actor/event01.json", // イベントリスト
      "animateSprites": "chest01_c0.png,chest01_c1.png", // アニメーションの順番
      "xPos":"3", // 初期X座標
      "yPos":"10" // 初期Y座標
    },
    ~~~ 省略 ~~~
    {
      "comment" :"ごぶりん1",
      "id":"0004",
      "move": "static_move", // static_move => その場足踏み
      "collision":"ng",
      "image": "actor01.png",
      "json" : "/actor/event01.json",
      "animateSprites": "enemy02_c0.png,enemy02_c1.png",
      "xPos":"16",
      "yPos":"12",
      "events": ""
    },
  ]
}

このようにイベント用の配列を作り、1イベント10個の要素を持つとした場合に
どのイベントも要素を10個持っていればマップとレイヤーの関係と同じ考え方で、
+10をすれば次のイベントにアクセスできるというわけです。

このやり方であれば多次元配列を使う必要はありませんね。

javascriptの配列は型がきまっていなく数値でも文字列でも添え字が違えば好きなものを入れられます。

しかしプチコンの場合というか大抵のプログラミング言語は数値を入れたら数値しか入れられない配列。

文字列を入れたら文字列しか入れられない配列になります。

数字だけで管理してコメントを付けておくのが一番軽い書き方ですね。

しかしプチコンで作るときは最初は文字列の配列でイベントを管理した方が良いかもしれません。

数値も文字列として管理しておけば、数値変換すれば数値にできますからね。

ですが文字列を数値にするということはちょっと難易度が高くなるのでやりません。

各イベントのプログラムを考えてみよう

ここでいうプログラムはプログラミングではなく運動会とかのプログラム表と同じ意味で考えてください。

イベントのプログラム表とは、そのイベントは何をするかのリストをまとめたものですね。

次もjsonになってしまいますが1つ目のイベント、つまり宝箱の中身のイベント内容になります。

{
  "events":
  [
    {
      "eventType": "graphic_change",
      "spriteImage": "1",
      "target": "0001"
    },
    {
      "eventType": "message",
      "text":"プレイヤー は たからばこを あけた。"
    },
    {
      "eventType": "message",
      "text":"なんと! ドラゴンキラー が はいっていた!\nプレイヤー は ドラゴンキラー を そうび した!"
    },
    {
      "eventType": "message_clear",
      "text":""
    },
    {
      "eventType": "get_dragonkiller"
    },
    {
      "eventType": "hidden_Through",
      "target": "0001"
    }
  ]
}

たからばこイベントですね。

中身にはドラゴンキラーが入っているのが分かると思います。

ゲームをプレイしている人は宝箱をあけてアイテムを手に入れるというのは自然な流れだと思うのですが、
ゲームを作るとなるとアイテムを手に入れるだけでこのような手順を踏んでいるのです。

まず、宝箱を調べたら宝箱が開くグラフィックに変更します。

その後、プレイヤーが宝箱を開けたというメッセージをウィンドウに表示します。

メッセージ送りをすると、さらにメッセージが表示されアイテムを手に入れたことをプレイヤーに知らせます。

この時点で実際にドラゴンキラーは手に入れていません。

次に表示されたメッセージをウィンドウから消します。

そして次のイベントに移ったときにはじめてドラゴンキラーを入手できます。

この時は装備システムを実装していなかったのでプレイヤーの攻撃力を増加する仕組みにしました。

このまま終わってしまうとまだ宝箱がある状態なのでもう一度調べたらドラゴンキラーを入手するイベントが発動します。

これでは無限ドラゴンキラーになってしまいますね。

なので最後はイベントレイヤーの数値を書き換えてイベントを発動させないようにしています。

たからばこをあけるだけですさまじい量のイベント数

毎回こんなこと書かなきゃゲーム作れないのか(絶望

ってなるかもしれませんが宝箱イベントなんて特別なものじゃない限りは全部一緒です。

なので宝箱イベントを関数1つにまとめて、イベントを調べた時にイベントタイプを何か調べたり、
idを見て何のイベント化調べてからアイテムであれば引数にアイテムidを渡せば使いまわせますね。

イベントがモンスターの場合は、条件分岐でバトルシーンに切り替える感じです。

RPGを作るな!RPGを作れ!

以上のことからイベントシステム作りの大変さをわかっていただけたと思います。

RPGツクールMVは当時海外版が先行して発売され価格も1万越えとSFC時代をほうふつさせる値段でした。

普通の人なら高い!と思うのでしょうがこうやってゲームを作ってみると、
如何にあの値段設定が安いかが分かります。

イベントシステムの説明で文字だけでもこんなに説明が長くなるのに、それをコーディングしようともなると結構ゾっとしますよね。

なのでぶっちゃけてしまうとRPGはゲーム作り初心者がするべきではありません。

ですが、RPG作りはプログラミング初心者はやるべきです。

何言ってんだコイツと思われるかもしれませんが、挫折を味わうことも含めての話です。

なぜRPGを作るのか

なぜ私がRPG作りに拘るかというと、ただ単に古き良き時代のRPGが好きなだけです。

それ以外の理由は一切ありません。

ゲーム作り初心者は倉庫番のようなゲームやシューティングが基本になると思います。

これを言うとシューティング好きを敵に回すかもしれませんが私はシューティングが苦手ですし、
ぶっちゃけやっていても楽しくないというのが本音です。

やってても楽しくないものを作っても楽しくないんですよね。

そもそも戦艦とか戦闘機が弾を撃ってっていうのがそもそも好きじゃありません。

シューティングを作るのはプログラミングの勉強としては正直RPGよりもいい題材ですが、
楽しくないの一言に尽きます。

私は剣と魔法にスチームパンクを足したようなコテコテな中世風ファンタジー世界が大好きなので、
初めてのゲームプログラミングもRPGつくりから始めようとしました。

当時はRPGを作りたいのではなくプログラミングでRPGを作りたいという謎のこだわりが強すぎたせいもあったのかもしれません。

今思うと無謀でしかなかったですし、怠惰そのものともいえる人間でしたから全て挫折してきました。

そりゃFFやドラクエのようなものを作ろうとしていたのですから当然ですね。

複数人が人生をかけて作ったゲームを怠け癖の付いた無知な人間一人で完成させられるわけがないのです。

何度も挫折するうちに心が折れてRPGツクールに回帰したのですが、デフォルトのグラフィックや効果音がショボかったりして
理想とかけ離れたようなもので途中で投げてしまう始末です。

SFC時代のツクールは良かったのですがPC版のツクールは効果音がなんかしょぼいんですよね。

BGMはすごく良いのですが……

と、ツクールの話になっているので話を戻します。

RPGを自作しようとして数々の挫折をしてきた私ですが、
32歳にしてやっと1つすさまじくしょぼいRPGを完全自作で完成させることが出来ました。

完全自作RPG

しかもGW中の8.5日を使って0ベースから一気に完成させました。

22歳頃からプログラミングをやってきたことが初めて報われたような感じがしました。

逆に10年プログラミングやってまだこのレベルなのかよって言われると何も言い返せませんが(笑)

このゲームはjavascriptで作ってElectronという特殊なツールを使って動かし方をしているため、
公開方法に悩んでしまってどうしようかと考えていたところ、復習がてらにプチコンに移植しようと思い本講座を始めた口です。

プチコンであればWiiUでも3DSでも遊べてしまいますからね。

基本コードを書いておけばプチコン4が出た時に移植も楽ですから今のうちに勉強しているわけです。

ちょっと自分語りになってしまいましたのでここで〆させていただきます。

次回からはイベントシステムを実際に作っていきましょう。

別ファイルにしたり配列を複数使ったり、ここからかなり作りが複雑になってくるので細かく説明しながら作っていく予定です。

それでは。