初始化仓库

This commit is contained in:
2026-08-10 23:35:23 +08:00
commit 8399ee5664
48 changed files with 1097 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
## 全局游戏状态(Autoload 单例)。
## 负责场景间参数传递与会话状态管理,不持有游戏内数据。
extends Node
## 进入游戏的方式。
enum GameMode { NEW_GAME, LOAD_GAME }
## 当前进入游戏的方式。
var mode: GameMode = GameMode.NEW_GAME
## 当前存档组 ID(两级存档第一级,SaveSystem 分配)。
var profile_id: int = 0
## 要加载的槽位文件名(仅 LOAD_GAME 时有效,如 "auto"/"slot_1754734800")。
var save_slot: String = ""
# 游戏内时间(12 月 × 30 天 = 360 天/年),实际推进由 TimeSystem 负责
var year: int = 1 # 年
var month: int = 1 # 月(1-12
var day: int = 1 # 日(1-30
## 请求开始新游戏。
## @param pid: 新存档组 ID(主菜单创建)
func request_new_game(pid: int) -> void:
mode = GameMode.NEW_GAME
profile_id = pid
save_slot = ""
year = 1
month = 1
day = 1
## 请求加载指定存档。
## @param pid: 存档组 ID
## @param slot_name: 槽位文件名(不含 .json
func request_load_game(pid: int, slot_name: String) -> void:
mode = GameMode.LOAD_GAME
profile_id = pid
save_slot = slot_name
+1
View File
@@ -0,0 +1 @@
uid://c0o83k384x3wp
+7
View File
@@ -0,0 +1,7 @@
[gd_scene format=3 uid="uid://c1exffg84ojqx"]
[ext_resource type="PackedScene" uid="uid://q1b6t22ej3ej" path="res://src/UI/Panels/MainMenu/MainMenu.tscn" id="1_g6xmk"]
[node name="MainGame" type="Node" unique_id=42551660]
[node name="MainMenu" parent="." unique_id=285750365 instance=ExtResource("1_g6xmk")]
+21
View File
@@ -0,0 +1,21 @@
## 用户设置(Autoload 单例)。
## 负责个人偏好设置的持久化,保存于 user:// 目录,与游戏存档分离。
extends Node
## 设置文件的保存路径。
const SAVE_PATH := "user://settings.cfg"
## 新游戏开局时的默认流速档位索引(1 = 5x)。
var default_speed_index := 1
## 从磁盘加载设置(不存在则保持默认值)。
func load_settings() -> void:
var cfg := ConfigFile.new()
if cfg.load(SAVE_PATH) == OK:
default_speed_index = cfg.get_value("time", "speed_index", 1)
## 将当前设置写入磁盘。
func save_settings() -> void:
var cfg := ConfigFile.new()
cfg.set_value("time", "speed_index", default_speed_index)
cfg.save(SAVE_PATH)
+1
View File
@@ -0,0 +1 @@
uid://dpnjkyle57umm
+139
View File
@@ -0,0 +1,139 @@
## 全局时间系统(Autoload 单例)。
## 负责游戏时间的推进与播报,仅在世界场景中运行。
## 历法:12 月 × 30 日 = 360 日/年。
extends Node
## 每当推进一日后发出。
## @param year: 当前年份
## @param month: 当前月份(1-12
## @param day: 当前日(1-30
signal day_passed(year: int, month: int, day: int)
## 每当进入新月份时发出(同一天内 day_passed 之后)。
## @param year: 当前年份
## @param month: 当前月份(1-12
signal month_passed(year: int, month: int)
## 每当进入新年份时发出(同一天内 month_passed 之后)。
## @param year: 当前年份
signal year_passed(year: int)
## 时间流速档位变化时发出。
## @param speed_index: 新档位在 SPEEDS 中的索引
signal speed_changed(speed_index: int)
## 暂停状态变化时发出。
## @param paused: 是否已暂停
signal pause_changed(paused: bool)
## 可选的时间流速倍率档位。
const SPEEDS := [1.0, 5.0, 20.0]
## 每月的天数。
const DAYS_PER_MONTH := 30
## 每年的月数。
const MONTHS_PER_YEAR := 12
## 现实世界每 1 天对应的时长(秒)。
const DAY_LENGTH := 0.5
## 当前流速档位在 SPEEDS 中的索引。
var speed_index := 0
## 当前流速倍率(与 SPEEDS[speed_index] 保持一致)。
var speed := 1.0
## 是否暂停时间推进。
var paused := false
## 已累积的现实时间(秒),未满 1 天。
var _elapsed := 0.0
## 每帧累积时间,满一天推进日期(仅游戏世界场景内)。
func _process(delta: float) -> void:
if paused or not _is_in_game():
return
_elapsed += delta * speed
if _elapsed >= DAY_LENGTH:
_elapsed -= DAY_LENGTH
_advance()
## 判断当前场景是否为游戏世界场景(主菜单/存档界面不推进时间)。
## 通过 "game_scene" 分组识别,而非场景名。
func _is_in_game() -> bool:
var scene := get_tree().current_scene
return scene != null and scene.is_in_group("game_scene")
## 推进一日并广播对应信号,跨月/跨年时补发 month_passed / year_passed。
func _advance() -> void:
var new_month := false
var new_year := false
GameState.day += 1
if GameState.day > DAYS_PER_MONTH:
GameState.day = 1
GameState.month += 1
new_month = true
if GameState.month > MONTHS_PER_YEAR:
GameState.month = 1
GameState.year += 1
new_year = true
day_passed.emit(GameState.year, GameState.month, GameState.day)
if new_month:
month_passed.emit(GameState.year, GameState.month)
if new_year:
year_passed.emit(GameState.year)
## 循环切换下一档流速,返回新倍率。
func cycle_speed() -> float:
speed_index = (speed_index + 1) % SPEEDS.size()
speed = SPEEDS[speed_index]
speed_changed.emit(speed_index)
return speed
## 应用用户设置中的默认流速档位(新游戏开局调用)。
func apply_default_speed() -> void:
set_speed_index(Settings.default_speed_index)
## 直接设置流速档位(越界自动钳制)。
## @param index: 目标档位索引
func set_speed_index(index: int) -> void:
speed_index = clampi(index, 0, SPEEDS.size() - 1)
speed = SPEEDS[speed_index]
speed_changed.emit(speed_index)
## 切换暂停状态,返回切换后的暂停状态。
func toggle_pause() -> bool:
paused = not paused
pause_changed.emit(paused)
return paused
## 显式设置暂停状态(幂等,状态未变化时不发信号)。
## @param value: 目标暂停状态
func set_paused(value: bool) -> void:
if paused == value:
return
paused = value
pause_changed.emit(paused)
## 当前流速的显示文本,如 "x5"。
func get_speed_label() -> String:
return "x%d" % int(speed)
## 当前日期数组 [年, 月, 日]。
func get_current_date() -> Array:
return [GameState.year, GameState.month, GameState.day]
## 当前日期文本,如 "3年 5月 12日"。
func get_date_text() -> String:
return "%d%d%d" % [GameState.year, GameState.month, GameState.day]
## 直接设置日期(供读档/测试使用)。
## @param y: 年
## @param m: 月(1-12
## @param d: 日(1-30
func set_date(y: int, m: int, d: int) -> void:
GameState.year = y
GameState.month = m
GameState.day = d
+1
View File
@@ -0,0 +1 @@
uid://b8f8t2phmhq2e