Godot4 ビッグカツブロック崩し28 セーブデータを管理するスクリプト例

※この連載の全ての記事は、タグ「ビッグカツ」の検索一覧から探すことができます。
※この連載で作ったゲームは「BigBreakOut(ゲームの作り方の記事付き) | フリーゲーム投稿サイト GodotPlayer」でプレイできます。

昔から人気の駄菓子「ビッグカツ」フリー素材画像が公開されたので、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 を使って、ビッグカツ画像を使ったブロック崩しを作成します。

「ビッグカツブロック崩し」作成の第28回では、設定した音量やゲームクリアの最速タイムのデータをセーブデータとしてセーブ・ロード・初期化・更新するスクリプト例を紹介します。
ゲーム起動中、常に存在してアクセスできるようにグローバルノードとして作成する手順をも紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。

前回の記事

前回は、タイトル画面で音量調節ができるスライダー UI を設定して、そのシグナルを受け取る関数を作成してテストしました。

セーブデータを管理するスクリプトの作成

セーブデータを管理するスクリプト (gd ファイル)を作成します。

ファイルシステムドックでスクリプトを配置するフォルダ(例では res://)を右クリックして表示されるメニュー「新規作成」→「スクリプト」を選択します。

Godot4 ビッグカツブロック崩し SaveData 用のスクリプトとグローバルノードの作成と設定1

パスにファイル名(例では save_data.gd)などを指定して「作成」ボタンを押します。
継承元のクラスは、自動読み込みでノードとして扱うため Node 以降のクラスを選択します。

Godot4 ビッグカツブロック崩し SaveData 用のスクリプトとグローバルノードの作成と設定2

アプリ起動時に自動読み込みされるグローバルノードに登録

作成した save_data.gd スクリプトを割り当てグローバルノードプロジェクト設定します。

メニュー「プロジェクト」→「プロジェクト設定」を選択します。

「プロジェクト設定」ウィンドウの「グローバル」→「自動読み込み」タブを開き、「パス」項目に先ほど作成した save_data.gd スクリプトを指定します。
※右側のフォルダアイコンのボタンから選択できます。

「ノード名」項目に、グローバルノードの名前(例では SaveDataGlobal )を設定します。
※ class_name で定義したクラス名と重複する名前は指定できません。

設定したら「追加」ボタンを押して、指定したスクリプトを割り当てられた、アプリの最初から最後まで存在するグローバルノード作成されます。

Godot4 ビッグカツブロック崩し SaveData 用のスクリプトとグローバルノードの作成と設定3

下図のように「自動読み込み」タブ内のリストに指定したスクリプトを割り当てたグローバルノードが追加されました。
アプリを実行した直後に root の下に配置され、アプリの終了時に自動的に解放されます。

Godot4 ビッグカツブロック崩し SaveData 用のスクリプトとグローバルノードの作成と設定4

セーブデータを管理するスクリプト例

辞書型(Dictionary)のセーブデータの変数を作成して、それを FileAccess の関数を用いてファイル出力・読み込みすることで、セーブとロードを行います。
キー(辞書型データの添え字になる文字列)がない場合は、既定の値を設定します。
※詳細はスクリプト内のコメントを参照してください。

extends Node
class_name SaveData
## セーブデータを管理するクラスです。プロジェクト設定の自動読み込みに設定しているグローバルなノードです。
## 以前に作成した TapTheTakarabako の記事も参照にしてください。
## https://compota-soft.work/archives/25627

## ベストタイム(ゲームクリアの最速タイム)です。
## -1 (0 未満) の場合は、まだ一度もクリアしていないので記録がない状態です。
var best_time: float = -1.0

## 音量です。 0.0 ~ 1.0 を指定します。
## タイトルのシーンの $HSliderSoundVolume スライダーで調整します。
var sound_volume: float = 0.5

## セーブデータの保存先です。
## Windows の場合は、このパスで使われている user:// は
## "%APPDATA%\Godot\app_userdata\プロジェクト名\" を指します。
var save_path = "user://BigBreakOut.save"

# Called when the node enters the scene tree for the first time.
func _ready():
	# オートロード(自動読み込み)でゲーム起動時に SaveDataGlobal ノードが root の下に配置される際に
	# 呼び出され、ゲーム起動直後にセーブデータを読み込みます。セーブデータがない場合はそれに対応する変数を初期化します。
	load_app_data()
	return

## セーブデータを保存します。
## F6 キーで保存されない場合、 F5 キーで実行するとロードとセーブができるかもしれません。
## プレイ中の BestTime のラベルの表示を更新するには ステージのシーンの $BestTime.update_label() を呼び出してください。
func save_app_data()->void:
	# セーブデータの変数を作成して、保存したい項目を設定します。
	var save_data = {}
	save_data["best_time"] = best_time	# スコア
	save_data["sound_volume"] = sound_volume # 音量
	
	# セーブファイルを書き込みモードで開きます。
	var f = FileAccess.open(save_path, FileAccess.WRITE)	
	# セーブデータの変数を文字列に変換して、セーブファイルに書きます。
	var s = var_to_str(save_data)
	f.store_string(s)	
	# ファイルを閉じます。
	f.close()
	return

## セーブデータをロードします。なければ既定値で初期化します。
## プレイ中の BestTime のラベルの表示を更新するには ステージのシーンの $BestTime.update_label() を呼び出してください。
func load_app_data()->void:
	var save_data: Dictionary

	# セーブファイルが存在する場合
	if FileAccess.file_exists(save_path):
		# ファイルを読み込み、セーブデータを変数に格納します。
		var f = FileAccess.open(save_path, FileAccess.READ)
		var s = f.get_as_text()
		save_data = str_to_var(s)
		# 使った後に、ファイルを閉じます。
		f.close()
	
	# 読み込んだセーブデータをメンバ変数や UI の値に反映します。
	# そのキーがない場合は、初期値を設定します。
	#   ベストタイム
	if not save_data.has("best_time"):
		save_data["best_time"] = -1.0
	best_time = save_data["best_time"]
	#   音量
	if not save_data.has("sound_volume"):
		save_data["sound_volume"] = 0.5
	sound_volume = save_data["sound_volume"]
	return

## ベストタイムを初期化します。
## プレイ中の BestTime のラベルの表示を更新するには ステージのシーンの $BestTime.update_label() を呼び出してください。
func init_best_time()->void:
	best_time = -1	# ベストタイムを初期値に変更します。
	save_app_data()	# セーブします。
	return

## ベストタイムのセーブデータを更新します。
## [param time] が [member best_time] より大きい(遅いタイム)の場合は更新しません。
func update_best_time_save_data(time: float)->void:
	if best_time < 0 or (best_time >= 0 and best_time > time):
		best_time = time	# タイムを更新します。
		save_app_data()	# セーブします。
	return

グローバルノードのセーブデータノードはいつでもアクセス可能

以下のスクリプトのように、グローバルノードにした SaveDataGlobal ノードには、シーン内のノードにアクセスするようにいつでも利用できます。
また、シーンが切り替わっても消えません
※アプリ終了時にシステムが自動的に削除するので、削除する必要はありません。

## 音量調節のスライダーからフォーカスが外れた際に、その音量をセーブします。
func _on_h_slider_sound_volume_focus_exited():
	# スライダー UI の現在選択されている音量の値(0.0 ~ 1.0) を取得して、セーブデータの変数を更新します。
	$"/root/SaveDataGlobal".sound_volume = $HSliderSoundVolume.value
	# セーブデータを保存します。
	$"/root/SaveDataGlobal".save_app_data()
	return

関連記事

自動読み込みのプロジェクト設定によるグローバルノードの設定については、以下の記事も参照してください。

まとめ

「ビッグカツブロック崩し」作成の第28回では、設定した音量やゲームクリアの最速タイムのデータをセーブ・ロード・初期化・更新するスクリプト例を紹介しました。
ゲーム起動中、常に存在してアクセスできるようにグローバルノードとして作成する手順をも紹介しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました