GameMaker 日本語掲示板

RPGのシナリオのプログラムの書き方について

5 コメント
views
16 フォロー

開発初心者です。
よくあるRPGゲームでは、NPCの前でボタンを押すとその場でプレイヤーが動かなくなり「ようこそ 〇〇のまちへ」のような会話が行われると思うのですが、どのようにプログラムを書けばよいのでしょうか。

シナリオに関しましては、
 ①noteファイルに1行ずつシナリオを記述する。
 ②file_text_open()関数でそのファイルを開く。
 ③file_text_read_string()関数を用いて配列に1行ずつ読み込む。
 ④それをdraw_text()関数を用いて画面に表示する。

と考えているのですがうまくいきません。
プレイヤーやゲーム自体を止めるポーズ機能に至っては全く分かりません。
プログラムの書き方、考え方について教えていただけると助かります。
よろしくお願いいたします。

mega
作成: 2021/03/13 (土) 19:51:07
最終更新: 2021/03/13 (土) 19:58:42
通報 ...
1

その動作を実装するためにはいろいろな要素が関わってくるので、まず切り分けて考えてみます。

  1. NPCの近くにいる判定
  2. ゲームをポーズ
  3. テキストを外部ファイルから読み込み
  4. 読み込んだテキストを1行ずつ表示(ボタンで送る)

(1)はpoint_distance()などで判定できます。

(2)のゲームポーズは、これだけで1つの大きなテーマになり得ます。ポーズ中のフラグでオブジェクトの処理をスキップさせる、ポーズの瞬間の画面を静止画で表示しその間オブジェクトを非アクティブにする、など複数の実現方法が考えられます。ポーズと言っても完全に全てを止めるのか一部だけを止めるのかなどいろいろあるので、どういうものを作りたいのか具体的に仕様をまとめるといいと思います。

(3)外部ファイルから読み込む方法も複数あります。file_text_read_string()でもいいと思いますし、JSONに対応することもできます。"read text file gamemaker"、 "dialogue system gamemaker"などで検索するといろいろ出てきます。

(4)表示はdraw_text()でいいと思います。「1行ずつ」を実現するには、これもいろいろ方法があるでしょうが、配列に1行ずつテキストを保持し、現在の行を保持する変数を作り、Drawイベントで現在の行のテキストを表示、ボタンで行を送れるようにする、という形でいいと思います。

できるだけ要素を区切って考えて、1つずつ個別に実装してみてください、そしてうまくいかなければ
その部分のコードをここに貼って質問もらえれば具体的な回答を得られると思います。

質問があるとこの掲示板が活発になり、他のgamemakerユーザーにも役立ちますので大変ありがたいです。
遠慮せず気軽にどしどし質問してください。
誰かが何かかしら教えてくれると思います!

2

どこまで出来ているのかが分からないので、もしすでに出来ていることならすみません。
まずこういうシンプルなものを作ってみてはどうでしょうか。

画像1
▲画面にhello!と表示するだけ。
それができたら、
Spaceキーを押したらhello!と出す動きにする。
それができたら、
Spaceキーを押すごとに、hello!→good!→tank you! とテキストを順に表示する動きを実装する。

それができたら、キャラクターを動かす部分と「NPCの近く」の判定を実装。

自キャラを矢印キーで動かし、NPC(移動はしない)の近くでSpaceキーを押すとテキストを表示する。
画像1

このように、要素を切り分けて1つずつ実装していってみるのをおすすめします。
そうすると何が出来て何ができないのかも分かると思います。

3

ご丁寧にありがとうございます。
細分化の考え方 非常に勉強になりました。

NPCの近くでSPACEキーを押すとシナリオが流れる機能と、全てのシナリオが終わるまでプレイヤーのスピードを0にしてキー受付を中断する簡単なポーズ機能は実装できました。
ですが各NPCにシナリオを割り当てる方法しか実装できず、色々調べてみたのですがテキストファイルを開いて配列に代入する方法がわかりませんでした。
シナリオはテキストファイルに一括で管理するイメージなので教えていただけるとありがたいです。

file_open_read()で開きfile_text_read_string()で配列に代入してfile_close()で閉じる流れはわかるのですが、テキストファイルの位置を指定してもファイルを開く関数でエラー(-1)が出てしまいます。

コード(NPCオブジェクトのcreateイベント内に記述しています)
fid = file_text_open_read("text.txt");
show_debug_message(fid);
str[0] = file_text_read_string(fid);
file_text_readln(fid);
str[1] = file_text_read_string(fid);
file_text_close(fid);

エラー文
ERROR!!! :: Failed to open file: text.txt
-1
ERROR!!! ::
ERROR in
action number 1
of Create Event
for object oNPC2:

File is not opened for reading.
 at gml_Object_oNPC2_Create_0 (line 7) - str[0] = file_text_read_string(fid);
画像1

4
asa 2021/03/15 (月) 13:00:05 修正

ファイル読み込みの部分がうまくいってないようですね。

GMSのファイル読み書きのデフォルトのパスは確か
C:\Users\UserName\AppData\Local\ProjectName\
ですのでここにファイルがある必要があります。

ここにtext.txt(UTF-8で保存したもの)を置いて、これが動くか試してみてください。

var _file = file_text_open_read("text.txt");
var _str = file_text_read_string(_file);
show_debug_message("_str="+string(_str))
file_text_close(_file);

正しく読み込まれて動作すればこうなります。
画像1

ゲームからファイルを作成し、書き込み読み込みをする処理の場合はこれでいいと思います。
(ゲームのコンフィグデータなど)

ですが、シナリオのテキストは予め自分で作ったテキストファイルをゲームに付属させる形になると思います。
ゲームを配布する時に、ユーザーのPCにこれをどうやって配置すればいい?となりますよね。
プロジェクトにファイルをインクルードすることで実現できます。

画像1
リソースツリーのところからファイルをインクルードすると、プロジェクトのフォルダ内にdatafilesというフォルダが作られ、そこにファイルがコピーされます。これで完了。開発環境でも動くし配布したゲームも動くはずです。テキストを編集する際はdatafilesにあるファイルを編集してください。

配布するゲームをビルド(Ctrl+F8)すると、このファイルはexeファイルと同じ場所に付属する形でコピーされるはずです。やってみてください。

ゲームを遊ぶユーザーから見ると、exeファイルがある場所にtext.txtがあるので開けば見たり編集できます。それをできにくくするなら暗号化したりという手段があります。それも解読不可能では無いと思うので、絶対見られたくないならシナリオテキストもプロジェクトのコード内に書く形にするしか無いのかなと思います。その場合でもリバースエンジニアリングで読まれる可能性は残ります。

私が書けるのはこんな感じで、「よく分からないがこうすると動く」的なことだけです。
コンピュータ、GMSのファイルI/Oについて、詳しい方からの解説を待ってます!
(サンドボックスとは?など私もちゃんと理解したい)

5

!!
解決しました!ありがとうございました!
また活用させていただきます