RPGのイベント処理について
RPGのイベント処理について
はじめまして、1年程前よりC言語を勉強しながら、DxLibを使ってゲームを作成しようと頑張っております。
こちらのサイトは最近よく拝見させて頂いております。はじめての質問となりますので、失礼等あるかと思いますが宜しくお願いいたします。
さて質問内容ですが、RPGでMAPを移動中にイベント(この場合特定の場所での発生)を発生させる方法がよくわかりません。
私個人の現時点のスキルは、
・キャラの表示と移動
・マップチップを使用してのMAPの表示及びスクロール表示
・上記2種類の同時処理(MAPを表示して自キャラを移動させる)
この程度です。
質問に不十分な点があるかと思いますが、よろしくお願いいたします。
PS・現時点ではソースはありません(この処理でつまづき、削除してしまいました・・・)
こちらのサイトは最近よく拝見させて頂いております。はじめての質問となりますので、失礼等あるかと思いますが宜しくお願いいたします。
さて質問内容ですが、RPGでMAPを移動中にイベント(この場合特定の場所での発生)を発生させる方法がよくわかりません。
私個人の現時点のスキルは、
・キャラの表示と移動
・マップチップを使用してのMAPの表示及びスクロール表示
・上記2種類の同時処理(MAPを表示して自キャラを移動させる)
この程度です。
質問に不十分な点があるかと思いますが、よろしくお願いいたします。
PS・現時点ではソースはありません(この処理でつまづき、削除してしまいました・・・)
Re:RPGのイベント処理について
私もRPGを作ってますよ^^
ポケモンですけど・・・
私も今イベントの処理に手を出しているんですが、同じく悩んでます。
今私の持っているアイデアとしてはこうです。
場合分けが大変そうですが^^;
他に良い案はないでしょうか?
ポケモンですけど・・・
私も今イベントの処理に手を出しているんですが、同じく悩んでます。
今私の持っているアイデアとしてはこうです。
MAP 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 0 上のマップをフィールドマップとは別に イベント発生用のマップデータだとします。 ということは宣言としては int map_data[2][Y_MAX][X_MAX]; といったとこでしょうか? イベント終了済みフラグが立っていなければ、 自キャラが”1”に来たらイベント1の処理 自キャラが”2”に来たらイベント2の処理 イベント終了後、フラグを立てておくでもこれだと少し大規模なRPGの制作になると、
場合分けが大変そうですが^^;
他に良い案はないでしょうか?
Re:RPGのイベント処理について
一度書いたので、もう一度・・・w
自分なりのイベントの解釈をしていますので、
参考にはならないかも知れません。。
(イベント=ノベル+キャラの自動動作)
敵と遭遇させるなら管理人さんのコードを参考にすると
手っ取り早いです。
以下は、「町の全員に話しかけて、空の見えるところに行ったらイベント発生」
について書いてみます。
まず、フィールドマップから町に入ります。
最初のキャラ描写位置は32×32を基準として
キャラの座標(10,15)とします。(640×480の画面真ん中下)
そこからキー入力に対応させてキャラの座標を変化させていきます。
条件は「町人全員に話しかける」ですので、条件を満たしたら、
フラグか何かを立ててやれば問題ないです。
そして「空の見える場所」は
0<=X<=20
y<3
という条件にしておいて、これを満たしたらイベントへ。
この時、X,Y座標がばらばらだと後で面倒なので、
初期化の意味も込めてキャラの座標をある特定のところへ。
こんな感じで自分は実装してました。(もはや過去形)
あとイベント中のキャラの自動動作、ノベルですが、
コードに直接描くのは管理、効率を考えてやめておいたほうが良いです。
自分は独自のスクリプトを(ほんの少し)作りました。
↓でこのことを質問してました。
http://www.play21.jp/board/formz.cgi?ac ... &rln=28553
作成したのは質問に書いたものとほぼ同じです。
・(ある座標(X1,Y1)から)(ある座標(X2,Y2)まで)(独自の速度vで)歩く
・その場から(X,Y)を中心とする円を描きながら歩行する。
・高さhまで重力加速度aの条件でジャンプする
・キャラが複数いたら、↑の動作の順番を定義する
の4つ+αを作りました。
これらを外部ファイルから読み取れるようにしました。
が、御津凪さんのアドバイスが作って初めて理解できました。
結構大変です。
なので、大規模にしないならイベントのキャラ自動動作は
後回しにしておいたほうがよいです^^;w
画面描写しておいて、ノベルを出すにする方針をおススメします。
>s-rushさん
自分も最初は管理のしやすさを考慮してそうしましたが、
よくよく考えたらメリットはあまりない気がしました。
やはりまず無駄が多い気がするのです。
っというのも町ひとつでベント発生場所なんてあって数か所だと思います。
(戦略ゲーはもっと多いかも知れませんが・・・)
あと使っていて思ったのが、ツールがないとマップデータ作ること自体意外と面倒です。
まぁ、今そのツール作る勉強しているのですが・・・w
なので自分はしっかりと内容を明記し、コードに直接かきました。(条件範囲座標)
自分なりのイベントの解釈をしていますので、
参考にはならないかも知れません。。
(イベント=ノベル+キャラの自動動作)
敵と遭遇させるなら管理人さんのコードを参考にすると
手っ取り早いです。
以下は、「町の全員に話しかけて、空の見えるところに行ったらイベント発生」
について書いてみます。
まず、フィールドマップから町に入ります。
最初のキャラ描写位置は32×32を基準として
キャラの座標(10,15)とします。(640×480の画面真ん中下)
そこからキー入力に対応させてキャラの座標を変化させていきます。
条件は「町人全員に話しかける」ですので、条件を満たしたら、
フラグか何かを立ててやれば問題ないです。
そして「空の見える場所」は
0<=X<=20
y<3
という条件にしておいて、これを満たしたらイベントへ。
この時、X,Y座標がばらばらだと後で面倒なので、
初期化の意味も込めてキャラの座標をある特定のところへ。
こんな感じで自分は実装してました。(もはや過去形)
あとイベント中のキャラの自動動作、ノベルですが、
コードに直接描くのは管理、効率を考えてやめておいたほうが良いです。
自分は独自のスクリプトを(ほんの少し)作りました。
↓でこのことを質問してました。
http://www.play21.jp/board/formz.cgi?ac ... &rln=28553
作成したのは質問に書いたものとほぼ同じです。
・(ある座標(X1,Y1)から)(ある座標(X2,Y2)まで)(独自の速度vで)歩く
・その場から(X,Y)を中心とする円を描きながら歩行する。
・高さhまで重力加速度aの条件でジャンプする
・キャラが複数いたら、↑の動作の順番を定義する
の4つ+αを作りました。
これらを外部ファイルから読み取れるようにしました。
が、御津凪さんのアドバイスが作って初めて理解できました。
結構大変です。
なので、大規模にしないならイベントのキャラ自動動作は
後回しにしておいたほうがよいです^^;w
画面描写しておいて、ノベルを出すにする方針をおススメします。
>s-rushさん
自分も最初は管理のしやすさを考慮してそうしましたが、
よくよく考えたらメリットはあまりない気がしました。
やはりまず無駄が多い気がするのです。
っというのも町ひとつでベント発生場所なんてあって数か所だと思います。
(戦略ゲーはもっと多いかも知れませんが・・・)
あと使っていて思ったのが、ツールがないとマップデータ作ること自体意外と面倒です。
まぁ、今そのツール作る勉強しているのですが・・・w
なので自分はしっかりと内容を明記し、コードに直接かきました。(条件範囲座標)
Re:RPGのイベント処理について
> でもこれだと少し大規模なRPGの制作になると、
> 場合分けが大変そうですが^^;
2D のマップチップ単位でのイベント判定を用意するのであれば、
容易な方法としては問題ないと思われますよ。
もう少し効率的な方法を説明すると、
イベントにも種類がある(マップ移動・人物に話しかけるなど)ので、
イベント番号を0~49までをマップ移動用に、50~199までを人物系イベント(動くイベント)
といったカテゴリわけをするように管理するといいと思います。
マップチップ単位でキャラが移動する場合、イベントの発生タイミングが色々と出てきます。
・イベントの場所に移動しようとした瞬間
・イベントの場所に移動した直後
・イベントとぶつかった時
・イベントの場所で調べる動作をした時
など。
(ここらへんはRPGツクール系のツールを遊んだことがあれば分かりやすいと思います)
ちなみに、些細な処理(マップに出入りした時の処理など)もイベントとして処理しておくと
管理がしやすい良いです。
そんなにイベント量の少ないゲームであれば、以下のような関数ポインタを使ったテーブルを用意することで
場合分けを使用せずに済ませることが出来ます。
> kazuoni さん
> 町ひとつでベント発生場所なんてあって数か所だと思います。
人物・立て札などの調べられるオブジェクト・マップ移動などをイベントとして括ると、
凝ったマップであれば結構な量になりますよ。
(カジノとか謎解き部屋とか)
# 3Dなど、ブロック単位でイベントを置かないタイプの場合は、
# 当たり判定などを利用してイベントを発生させます。
# この場合のイベントの管理はリストとしてマップごとに持たせたほうが良いでしょう。
> 場合分けが大変そうですが^^;
2D のマップチップ単位でのイベント判定を用意するのであれば、
容易な方法としては問題ないと思われますよ。
もう少し効率的な方法を説明すると、
イベントにも種類がある(マップ移動・人物に話しかけるなど)ので、
イベント番号を0~49までをマップ移動用に、50~199までを人物系イベント(動くイベント)
といったカテゴリわけをするように管理するといいと思います。
マップチップ単位でキャラが移動する場合、イベントの発生タイミングが色々と出てきます。
・イベントの場所に移動しようとした瞬間
・イベントの場所に移動した直後
・イベントとぶつかった時
・イベントの場所で調べる動作をした時
など。
(ここらへんはRPGツクール系のツールを遊んだことがあれば分かりやすいと思います)
ちなみに、些細な処理(マップに出入りした時の処理など)もイベントとして処理しておくと
管理がしやすい良いです。
そんなにイベント量の少ないゲームであれば、以下のような関数ポインタを使ったテーブルを用意することで
場合分けを使用せずに済ませることが出来ます。
// イベントパラメータ typedef struct { short player_x,player_y; // プレイヤーの位置 short event_x,event_y; // イベントの位置 int trigger; // イベント発生の引き金(進入・調べるなどの識別値) } SEventParam; // イベント関数型の定義。 typedef void (*EventFunc)( SEventParam *ev ); // 0~255番までのイベントテーブルを用意 EventFunc gEventTable[256] = { NULL, // 0番は必ず発生させないようにする(イベントマップでの 0 を存在しないイベントとするため) /* ここに番号順にイベント関数を入れる。 (空白箇所は NULL で埋める) */ }; // イベント関数を呼び出す関数 void CallEvent( int evId, SEventParam *ev ){ if(gEventTable[evId]) gEventTable[evId](ev); }この方法なら、switch 文を使わずに記述できますし、イベントIDの領域が 256 未満に収まるのであれば、
unsigned char ev_data[Y_MAX][X_MAX];と、マップとは別型で小さく宣言することができ、領域は4分の1に収まるはずです。
> kazuoni さん
> 町ひとつでベント発生場所なんてあって数か所だと思います。
人物・立て札などの調べられるオブジェクト・マップ移動などをイベントとして括ると、
凝ったマップであれば結構な量になりますよ。
(カジノとか謎解き部屋とか)
# 3Dなど、ブロック単位でイベントを置かないタイプの場合は、
# 当たり判定などを利用してイベントを発生させます。
# この場合のイベントの管理はリストとしてマップごとに持たせたほうが良いでしょう。
Re:RPGのイベント処理について
>人物・立て札などの調べられるオブジェクト・マップ移動などをイベントとして括ると
これはごもっともです^^;
自分はストーリイベントとは別に管理していましたが・・・
確かに実現できそうです。
3Dのあたり判定・・・めんどくさそうですね^^;
ただ、今のゲームは3Dが当たり前になってるので、
いろいろな考え方を学ぶのって重要かもしれないですね・・・。
これはごもっともです^^;
自分はストーリイベントとは別に管理していましたが・・・
確かに実現できそうです。
3Dのあたり判定・・・めんどくさそうですね^^;
ただ、今のゲームは3Dが当たり前になってるので、
いろいろな考え方を学ぶのって重要かもしれないですね・・・。
Re:RPGのイベント処理について
沢山の回答ありがとうございます。
サンプルプログラムも参考にさせて頂いておりました。やはり別配列を用意して管理するのが良いようですね。
MAPもファイルからデータを読み込んで表示してるんですけど、イベントもそれと同じような感じでデータを用意して、それを関数ポインタ等で処理を振り分ける的な・・・
私はゲームの作成経験がないもので、一般的な処理がどうなっているのか見当がつかず悩んでました。
しかし皆様の回答を見せて頂いた感じでは、概ね考え方自体は間違っていない事がわかりました。
ありがとうございます。
ただひとつ気になるのは、配列でイベントを管理した場合、町等の狭い範囲ならば問題ないのですが、フィールドのような広い範囲を配列で用意すると、メモリ等は大丈夫なのでしょうか?
サンプルプログラムも参考にさせて頂いておりました。やはり別配列を用意して管理するのが良いようですね。
MAPもファイルからデータを読み込んで表示してるんですけど、イベントもそれと同じような感じでデータを用意して、それを関数ポインタ等で処理を振り分ける的な・・・
私はゲームの作成経験がないもので、一般的な処理がどうなっているのか見当がつかず悩んでました。
しかし皆様の回答を見せて頂いた感じでは、概ね考え方自体は間違っていない事がわかりました。
ありがとうございます。
ただひとつ気になるのは、配列でイベントを管理した場合、町等の狭い範囲ならば問題ないのですが、フィールドのような広い範囲を配列で用意すると、メモリ等は大丈夫なのでしょうか?
Re:RPGのイベント処理について
追記です。
kazuoni様
> あと使っていて思ったのが、ツールがないとマップデータ作ること自体意外と面倒です。
> まぁ、今そのツール作る勉強しているのですが・・・w
私は以前別の言語でゲーム作成に挑戦しようと思い、MAPエディターを自作しました。
その頃はファイルの読み書きの方法がよくわかっていなかったので、その部分は苦労しましたが、
それ以外はそれほど面倒な処理はなかったです。(あくまでも自分が使えれば良いという程度の物ですが)
まだC言語でそれを作成した事はありませんが、これからMAPエディターにも挑戦しようと思います。
いつになるかわかりませんが・・・(汗)
kazuoni様
> あと使っていて思ったのが、ツールがないとマップデータ作ること自体意外と面倒です。
> まぁ、今そのツール作る勉強しているのですが・・・w
私は以前別の言語でゲーム作成に挑戦しようと思い、MAPエディターを自作しました。
その頃はファイルの読み書きの方法がよくわかっていなかったので、その部分は苦労しましたが、
それ以外はそれほど面倒な処理はなかったです。(あくまでも自分が使えれば良いという程度の物ですが)
まだC言語でそれを作成した事はありませんが、これからMAPエディターにも挑戦しようと思います。
いつになるかわかりませんが・・・(汗)
Re:RPGのイベント処理について
広い範囲を二次元配列で用意する場合、
容量(バイト数) = 横幅 * 縦幅 * 型のバイト数
の式で求められます。
たとえば、縦横共に 1024 個の広大なフィールドを int 型で用意した場合、
1024 * 1024 * 4 = 4194304 Byte
で、4MB 必要になります。
しかし、マップチップのデータはチップの番号なので、 int 型も必要ないと思うので、
char (または unsigned char) 型にすると4分の1となり、1MBですみます。
どちらにしても、これぐらいでメモリ領域を圧迫するようなPCは今ではほとんどないので
さほど気にする点ではないかもしれませんが。
また、マップデータを保存する際、生のデータとして保存する場合には
上記式の容量+α(縦横幅などのマップ情報)のファイルサイズになります。
(バイナリ形式の場合です。テキスト形式はもっと膨大なサイズになります)
この場合は圧縮(zlibなど)ライブラリを使って圧縮保存し、読み込み時にメモリ領域に解凍・展開する方法が
良いと思います。
容量(バイト数) = 横幅 * 縦幅 * 型のバイト数
の式で求められます。
たとえば、縦横共に 1024 個の広大なフィールドを int 型で用意した場合、
1024 * 1024 * 4 = 4194304 Byte
で、4MB 必要になります。
しかし、マップチップのデータはチップの番号なので、 int 型も必要ないと思うので、
char (または unsigned char) 型にすると4分の1となり、1MBですみます。
どちらにしても、これぐらいでメモリ領域を圧迫するようなPCは今ではほとんどないので
さほど気にする点ではないかもしれませんが。
また、マップデータを保存する際、生のデータとして保存する場合には
上記式の容量+α(縦横幅などのマップ情報)のファイルサイズになります。
(バイナリ形式の場合です。テキスト形式はもっと膨大なサイズになります)
この場合は圧縮(zlibなど)ライブラリを使って圧縮保存し、読み込み時にメモリ領域に解凍・展開する方法が
良いと思います。
Re:RPGのイベント処理について
御津凪様、早速の回答ありがとうございます。
なるほど、1024×1024の配列を取ってもchr型ならば1Mですか・・・実際はそんなに大きなMAPにならないので、メモリの心配はないですね。
安心しました。
ただアドバイスの最後の部分
>この場合は圧縮(zlibなど)ライブラリを使って圧縮保存し、読み込み時にメモリ領域に解凍・展開する方法が良いと思います。
で、メモリ領域にファイルを解凍・展開するとは、どういう処理なんでしょうか?
ファイルというと、作成・圧縮・解凍したものは物理的にDISC上にできる物という知識しかないもので・・・
お手数でなければ、処理の簡単なヒントのような物でも結構ですので、お願いできますか?
なるほど、1024×1024の配列を取ってもchr型ならば1Mですか・・・実際はそんなに大きなMAPにならないので、メモリの心配はないですね。
安心しました。
ただアドバイスの最後の部分
>この場合は圧縮(zlibなど)ライブラリを使って圧縮保存し、読み込み時にメモリ領域に解凍・展開する方法が良いと思います。
で、メモリ領域にファイルを解凍・展開するとは、どういう処理なんでしょうか?
ファイルというと、作成・圧縮・解凍したものは物理的にDISC上にできる物という知識しかないもので・・・
お手数でなければ、処理の簡単なヒントのような物でも結構ですので、お願いできますか?
Re:RPGのイベント処理について
圧縮・解凍ソフトはファイルを対象にしたものですね。
この圧縮・解凍をする処理のみを使って、
メモリ上で圧縮したデータをファイルに保存したり、
圧縮したファイルをメモリ上で解凍してそのデータを使用するといったことが出来ます。
一番簡単に出来る圧縮ライブラリとして、上記では zlib を書きましたが、他にも bzip2 や LZMA SDK など、
いくつか無料で使用できるものもあります。
一応 zlib での使用方法として、下記のページを見てみると良いと思います。
(サンプルもあります)
http://oku.edu.mie-u.ac.jp/~okumura/com ... /zlib.html
この圧縮・解凍をする処理のみを使って、
メモリ上で圧縮したデータをファイルに保存したり、
圧縮したファイルをメモリ上で解凍してそのデータを使用するといったことが出来ます。
一番簡単に出来る圧縮ライブラリとして、上記では zlib を書きましたが、他にも bzip2 や LZMA SDK など、
いくつか無料で使用できるものもあります。
一応 zlib での使用方法として、下記のページを見てみると良いと思います。
(サンプルもあります)
http://oku.edu.mie-u.ac.jp/~okumura/com ... /zlib.html
Re:RPGのイベント処理について
御津凪様、回答ありがとうございます。
教えて頂いたzlibのサイトを見てみました。
ようはzlibのようなライブラリを使用してファイルを展開した場合、最初は配列(メモリ)に格納してしてあって、それをそのまま使えばアドバイスの様な処理になり、ファイルとして書き出せば物理的なファイルになる・・・このような考え方で良いのでしょうか?
教えて頂いたzlibのサイトを見てみました。
ようはzlibのようなライブラリを使用してファイルを展開した場合、最初は配列(メモリ)に格納してしてあって、それをそのまま使えばアドバイスの様な処理になり、ファイルとして書き出せば物理的なファイルになる・・・このような考え方で良いのでしょうか?
Re:RPGのイベント処理について
そのような考え方でいいと思います。
ただ、一つ気をつける点として、
通常、圧縮したデータには元のデータサイズの情報がないので、
解凍しきるまでデータサイズが分からないという点があります。
これは、読み込む際にメモリを動的に確保・拡張する必要があることを意味します。
ただ、一つ気をつける点として、
通常、圧縮したデータには元のデータサイズの情報がないので、
解凍しきるまでデータサイズが分からないという点があります。
これは、読み込む際にメモリを動的に確保・拡張する必要があることを意味します。
Re:RPGのイベント処理について
御津凪様をはじめ、kazuoni様、s-rush様、管理人様、沢山の回答ありがとうございました。
皆様のアドバイスでだいぶ処理が理解できましたので、がんばってRPGプログラムにチャレンジします。
また質問させて頂く事があると思いますが、その際はよろしくお願いします。
皆様のアドバイスでだいぶ処理が理解できましたので、がんばってRPGプログラムにチャレンジします。
また質問させて頂く事があると思いますが、その際はよろしくお願いします。