94 lines
2.8 KiB
GDScript
94 lines
2.8 KiB
GDScript
## SceneManager — 场景路由 + 黑幕淡入淡出(Autoload: SceneManager)
|
||
## 所有场景跳转必须经过此单例,保证转场动画一致。
|
||
extends Node
|
||
|
||
const FADE_DURATION: float = 0.35
|
||
|
||
## 下一次加载游戏场景时的启动模式
|
||
## "new"=新游戏 "continue"=读档继续 "endless"=无尽模式
|
||
var start_mode: String = "new"
|
||
var is_transitioning: bool = false
|
||
|
||
var _overlay: ColorRect = null
|
||
var _tween: Tween = null
|
||
|
||
# 场景路径注册表
|
||
const SCENES: Dictionary = {
|
||
"splash": "res://scenes/ui/splash.tscn",
|
||
"main_menu": "res://scenes/ui/main_menu.tscn",
|
||
"game": "res://scenes/main/combat_s2.tscn",
|
||
}
|
||
|
||
func _ready() -> void:
|
||
# 转场需在暂停态下也能运行(从暂停菜单返回主菜单等)
|
||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||
# 全屏黑幕覆盖层(始终在最顶层)
|
||
var cl := CanvasLayer.new()
|
||
cl.layer = 127
|
||
add_child(cl)
|
||
_overlay = ColorRect.new()
|
||
_overlay.color = Color.BLACK
|
||
_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
_overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||
cl.add_child(_overlay)
|
||
_overlay.modulate.a = 1.0 # 从黑屏开始,首屏淡入
|
||
|
||
func _fade_in(on_done: Callable = Callable()) -> void:
|
||
if _tween:
|
||
_tween.kill()
|
||
_tween = create_tween()
|
||
_tween.tween_property(_overlay, "modulate:a", 0.0, FADE_DURATION)
|
||
if not on_done.is_null():
|
||
_tween.tween_callback(on_done)
|
||
|
||
func _fade_out(on_done: Callable = Callable()) -> void:
|
||
if _tween:
|
||
_tween.kill()
|
||
_tween = create_tween()
|
||
_tween.tween_property(_overlay, "modulate:a", 1.0, FADE_DURATION)
|
||
if not on_done.is_null():
|
||
_tween.tween_callback(on_done)
|
||
|
||
## 通用跳转(不建议直接调用,优先用下方语义方法)
|
||
func goto(scene_id: String) -> void:
|
||
if is_transitioning:
|
||
return
|
||
is_transitioning = true
|
||
_fade_out(func():
|
||
get_tree().change_scene_to_file(SCENES[scene_id])
|
||
call_deferred("_after_scene_load")
|
||
)
|
||
|
||
func _after_scene_load() -> void:
|
||
_fade_in(func(): is_transitioning = false)
|
||
|
||
## ── 语义跳转方法 ────────────────────────────────────────────
|
||
|
||
func goto_splash() -> void:
|
||
goto("splash")
|
||
|
||
func goto_main_menu() -> void:
|
||
goto("main_menu")
|
||
|
||
## 启动新游戏(从头开始)
|
||
func start_new_game() -> void:
|
||
start_mode = "new"
|
||
goto("game")
|
||
|
||
## 继续上局存档
|
||
func continue_game() -> void:
|
||
start_mode = "continue"
|
||
goto("game")
|
||
|
||
## 初始淡入(场景 _ready 调用)。经 goto 进入时由 _after_scene_load 独占淡入,
|
||
## 此处跳过以免 kill 掉带"复位 is_transitioning"回调的转场 Tween(仅单独启动场景时淡入)。
|
||
func fade_in_first() -> void:
|
||
if is_transitioning:
|
||
return
|
||
_fade_in()
|
||
|
||
## 当前是否有可继续的存档
|
||
func has_save() -> bool:
|
||
return FileAccess.file_exists(ProfileManager.PATH_A) or \
|
||
FileAccess.file_exists(ProfileManager.PATH_B)
|