※本記事にはアフィリエイト広告(Udemy)を含みます。
前回のおさらい
前回⑦では、自動化モジュールでクリック操作を不要にし、JSON形式でのセーブ/ロードを実装しました。今回はシリーズ最終回として、案内役ECHOのセリフに演出を加え、BGMを組み込んだうえで、実際にWeb向けに書き出して公開するところまで行います。
今回のゴール
- 設備の段階が進むたびに、ECHOが一言コメントする
- 進行中にもランダムな雑談セリフを挟む
- BGMを組み込む
- Web (HTML5) 形式で書き出し、日本語の文字化けに対処したうえで公開する
段階が変わった瞬間のセリフを実装する
Signalで「段階が変わったこと」を通知する
これまでの記事で、発電パネル・酸素生成装置・部品工場・中央制御システムと、設備が段階的に増えていく設計にしてきました。この「段階が変わった」というタイミングを、新しいSignalとして通知するようにします。
signal stage_changed(new_stage: int)
var upgrade_stage: int = 0
発電パネルを初めて購入したときなど、各購入関数の中で段階が上がったタイミングにこのSignalを追加します。
func buy_power_panel() -> bool:
# (購入処理は④の内容と同じ)
if upgrade_stage < 1:
upgrade_stage = 1
stage_changed.emit(1)
resources_changed.emit()
save_game()
return true
酸素生成装置・部品工場・中央制御システム・自動化モジュールの購入関数にも、同じ要領でそれぞれupgrade_stageを2、3、4、5に進める処理とstage_changed.emit()を追加してください。
段階ごとのセリフを辞書で管理する
Main.gd側で、段階ごとのセリフをDictionary(辞書、キーと値の組み合わせでデータを持つ型)にまとめておきます。
const STAGE_INTRO_LINES: Dictionary = {
0: "ECHO: ようこそ。まずは手動で発電してみて。",
1: "ECHO: 発電パネル、設置できたね。",
2: "ECHO: 酸素生成装置が動き出した。",
3: "ECHO: 部品工場、稼働開始。",
4: "ECHO: 中央制御システム、接続完了。",
5: "ECHO: 自動化モジュール、起動。",
}
func _ready() -> void:
# (これまでの接続処理に追加)
GameManager.stage_changed.connect(_on_stage_changed)
func _on_stage_changed(new_stage: int) -> void:
if STAGE_INTRO_LINES.has(new_stage):
echo_dialogue.text = STAGE_INTRO_LINES[new_stage]
辞書を使うことで、「段階の数だけif文を並べる」という書き方を避け、セリフの追加・修正がしやすくなっています。
進行中に挟む雑談コメントを実装する
段階が変わった瞬間だけでなく、プレイ中にも時々ECHOが話しかけてくるようにします。
const AMBIENT_LINES: Array[String] = [
"ECHO: 電力、順調に増えてるね。",
"ECHO: この基地、静かすぎない?",
"ECHO: 数字が増えていくの、見てて飽きないな。",
]
var _ambient_timer: Timer
func _ready() -> void:
# (これまでの処理に追加)
_ambient_timer = Timer.new()
_ambient_timer.wait_time = 25.0
_ambient_timer.autostart = true
_ambient_timer.timeout.connect(_on_ambient_timer_timeout)
add_child(_ambient_timer)
func _on_ambient_timer_timeout() -> void:
echo_dialogue.text = AMBIENT_LINES[randi() % AMBIENT_LINES.size()]
randi() % AMBIENT_LINES.size()は、「0以上・配列の要素数未満」の範囲でランダムな整数を得るための書き方です。これにより、25秒ごとにセリフが1つランダムに選ばれて表示されます。
BGMを組み込む
- シーンにAudioStreamPlayerノードを追加する
- インスペクタの「Stream」に、用意した音楽ファイル(
.mp3など)を設定する - 「Autoplay」にチェックを入れる
- なぜ:ゲーム画面が開くと同時に再生を始めるためです
- スクリプトでループ設定を明示する
func _ready() -> void:
if $BGMPlayer.stream is AudioStreamMP3:
$BGMPlayer.stream.loop = true
フリーBGM素材を使う場合は、利用規約を必ず確認してください。サイトによっては著作権表示が必須の場合と不要な場合があり、ループ再生を前提に作られた「ループ版」の音源が別途用意されていることもあります。
日本語がWeb書き出しで文字化けする問題への対処
なぜデフォルトフォントでは日本語が表示できないのか
Godotの初期状態のフォントには、日本語の文字(グリフ)が含まれていません。エディタ上での実行時は、OS側が代わりに日本語フォントを補って表示してくれることがあるため気づきにくいのですが、Web書き出し後はこの補完が効かず、日本語部分が四角い文字化け(いわゆる「豆腐」)として表示されてしまいます。
日本語フォントをTheme経由で読み込む
- Noto Sans CJK JPなど、日本語を含むフォントファイルをプロジェクトの
assets/fontsフォルダに配置する - プロジェクトで使っているTheme(
.tres)リソースを開く - 「Default Font」に、配置したフォントファイルを設定する
- なぜ:Themeのデフォルトフォントを差し替えることで、個別のLabelやButtonごとに設定しなくても、UI全体に日本語フォントが適用されます
フォントファイルはサイズが大きくなりがちなので、実際にゲーム内で使う文字だけを抜き出した「サブセットフォント」を作成すると、読み込み時間を大きく短縮できます。fonttoolsというツールのpyftsubset機能を使うと、使用する文字だけを指定してフォントを軽量化できます。
Web (HTML5) 形式で書き出す
エクスポートテンプレートの準備
- Godotエディタのメニューから「エディタ」→「エクスポートテンプレートの管理」を開く
- 使用中のGodotバージョンに対応するテンプレートをダウンロードする
- なぜ:エクスポート機能はエディタ本体とは別に、書き出し用のテンプレートファイルを必要とするためです
書き出し手順
- メニューの「プロジェクト」→「エクスポート」を開く
- 「追加」から「Web」を選択する
- 出力先とファイル名を指定し、「プロジェクトをエクスポート」をクリックする
- なぜ:この操作で
index.html・.wasm・.pckなどのファイル一式が生成されます。これらはまとめて1セットとして扱う必要があります
自サイト・itch.ioへの公開
自サイトへの設置方法
書き出したファイル一式を、サーバー上の任意のフォルダにアップロードします。WordPressの記事や固定ページから、そのURLを<iframe>タグで埋め込む形が簡単です。
itch.ioへの公開手順
- itch.ioで新規プロジェクトを作成する
- アップロードしたZIPファイルに対して「This file will be played in the browser」を有効にする
- 「Embed options」で、実際の画面サイズに合わせてViewport Dimensionsを設定する
- 内容を確認し、問題なければ公開設定を「Public」に変更する
STATION OPSは、実際に以下で公開しています。
おわりに
全8回を通じて、Godotの基本機能であるControl(UI)、Timer、Signal、セーブ/ロード、Resourceの扱い方を、実際に手を動かしながら学んできました。放置ゲームという題材は規模が小さい分、1つ1つの機能の役割がつかみやすかったのではないかと思います。
なお、この後の制作過程では、背景の段階的な変化や評価ランク表示、隠しエンディングといった追加のブラッシュアップも行いました。こちらは当初の8回の範囲を超える内容のため、別途「番外編」として記事にまとめる予定です。
Godot学習におすすめのオンライン講座
今回で一通りの基本機能を学び終えましたが、応用的な内容やアセット制作なども含めて体系的に学び直したい方は、こうした講座もあわせて活用してみてください。


コメント