「 その選択肢を選んだあと 次の会話に つながってほしいのよ」
「 多分、それは メッセージ・ウィンドウの仕事ではなくて、
メッセージ・ウィンドウへ メッセージを手配してくる 交換手か何かの仕事だな」
「 ストーリーテラー(storyteller;語り部)のようなクラスでも 作るかだぜ?」
「 シナリオプレイヤー(Scenario Player;シナリオ再生機)ぐらいの造語でいいかな」
「 👆 じゃあ 空っぽの Node
をベースに シナリオプレイヤーを作ってしまおう。
細かいことは これから詰めていこう」
「 なんでもかんでも オートマトン(Automaton;自動人形)と同じように作ればいいんだろ。
ステートマシーンを持たせろだぜ」
📄 ScenarioPlayerStatemachine.gd
:
# シナリオ・プレイヤー・ステートマシーン(Scenario Player Statemachine;台本再生機状態遷移図)
extends Node
class_name ScenarioPlayerStatemachine
# 状態遷移図
# ーーーーー
#
# +ーーーーー+
# | はじめ |
# +ーー+ーー+
# |
# |
# +ーーーーーーーーーー>+
# | |
# | V
# | +ーーーーーーー+
# | | 0.停止中 |
# | +ーーー+ーーー+
# | |
# | | 再生 #ステートマシーン外部からの開始の合図。段落番号を渡される
# | |
# | +ーーーーーー>+
# | | |
# | | V
# | | +ーーーーーーー+
# | | | 1.再生中 |
# | | +ーーー+ーーー+
# | | |
# | | |
# | | |
# | +ーーーー<ーー+ 再生 #別の段落番号が書かれていた
# | はい |
# | |
# +ーーーーーーーーーーー+ 停止 #段落が終わった
#
enum States {None, Playing}
# 状態
var state = States.None
# 停止中か?
func is_none():
return self.state == States.None
# 再生中か?
func is_playing():
return self.state == States.Playing
# 再生
func play(paragraph_no):
print("[ステートマシーン] パラグラフの再生")
self.state = States.Playing
# 停止
func stop(paragraph_no):
print("[ステートマシーン] 停止")
self.state = States.None
「 そのステートマシーンを シナリオプレイヤーに実装しろだぜ」
📄 ScenarioPlayer.gd
:
# シナリオプレイヤー(Scenario Player;台本再生機)
extends Node
# 状態遷移機械
var statemachine = load("scripts/ScenarioPlayerStatemachine.gd").new()
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
if self.statemachine.is_none():
# 停止中
# 何もしない
pass
elif self.statemachine.is_playing():
# 再生中
# 何もしない
pass
「 シナリオプレイヤーは 自律的に動くといっても、
起動の合図は 外部から与えるのよね?」
「 じゃあ 本当に自律的に動く 監督 が必要なんじゃないの?」
「 👆 ルート・ノードの名前を Director
にしたった」
📄 Director.gd
:
# ディレクター(Director;監督)
# とりあえず、ゲーム全体をコントロールする
extends Node2D
# Called when the node enters the scene tree for the first time.
func _ready():
# シナリオ・ブックから、内容を取出す
print("[2Dプロジェクト] シナリオ・ブックから、内容を取出す")
var scenario_array = $"./ScenarioBook".scenario_array
# シナリオプレイヤーへ、内容を渡す
print("[2Dプロジェクト] シナリオプレイヤーへ、内容を渡す")
$"./ScenarioPlayer".set_scenario_array(scenario_array)
「 👆 監督のスクリプトの雰囲気は こんな感じになるはずだぜ」
「 シナリオブックの 各部分に パラグラフ(Paragraph;段落)番号を振れない?」
「 リストではなく マップが必要だな。 Godot にマップはあるのかだぜ?」
📄 ScenarioBook.gd
:
# 段落番号を指定して、段落を取得
func get_paragraph(paragraph_code):
return self.document[paragraph_code]
「 👆 段落番号を指定して、段落を取得できるメソッドを作っておくぜ。
あとで 1.2.3
みたいな段落番号を使いたいので、番号は文字列にしておくぜ」
「 👆 インデント2つが もったいない気がするが、
普通の書き方を優先し、上図のように セリフを並べることにするぜ」
「 👆 こんな風に パラグラフを追加していくものとしようぜ」
「 選択肢の1番目が 段落の 1.1
に飛ぶのを どうコントロールすんの?」
「 そのコントロールをするのが ScenarioPlayer
だぜ」
「 👆 こんな感じでマッピングするんだが、なんかよく分からないな」
「 どうやっても 分かんないんだから 2重の Dictionary
にしたらどうなの?」
「 👆 これで分岐の最低要件は満たせるが、確かに 見ても よく分からんよな」
「 この設定ファイルを編集する外部エディターぐらい お父ん 作れるだろ」
「 台詞だけで できたゲームなら これでいけるけど、
戦闘シーンや、マップや、ムービーに続けたいときは どうすんの?」
📺 動画
.
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント