xiandie/scene/ground/ground_loader.gd

200 lines
6.1 KiB
GDScript3
Raw Normal View History

@tool
class_name GroundLoader extends Node2D
@export_group("Scene")
@export var ignore_archive := false
@export var current_scene := "c02_s01"
@export var entrance_portal := "left"
@export var debug_reload := false:
set(new_val):
debug_reload = false
if current_scene and entrance_portal:
transition_to_scene(current_scene, entrance_portal, true)
@export var archive_scene := ""
@export var archive_portal := ""
2025-01-13 08:09:57 +00:00
var first_entered := true
var ground: Ground2D
var scenes_dir = "res://scene/ground/scene/"
var ground_dict = {}
func _ready() -> void:
_read_grounds()
ground = get_node_or_null("Ground")
# load save
if not ignore_archive:
_load_save()
if archive_scene and archive_portal:
current_scene = archive_scene
entrance_portal = archive_portal
if current_scene and entrance_portal:
transition_to_scene(current_scene, entrance_portal, true)
2025-01-13 08:09:57 +00:00
elif ground:
ground.queue_free()
ground = null
2025-01-14 00:56:51 +00:00
func _read_grounds() -> void:
# read grounds
var dir = DirAccess.open(scenes_dir)
for c_dir in dir.get_directories():
var c_path = scenes_dir + c_dir + "/"
for s_file in DirAccess.open(c_path).get_files():
if s_file.ends_with(".tscn"):
var s_path = c_path + s_file
ground_dict[c_dir.substr(0, 3) + "_" + s_file.substr(0, 3)] = s_path
2025-01-14 00:56:51 +00:00
# # 确保每个 ground 都初始化 archive
# for key in ground_dict.keys():
# if GlobalConfig.DEBUG:
# print("check ground_archive:", key)
# ArchiveManager.archive.ground_archive(key)
func _load_save():
if not Engine.is_editor_hint() and ArchiveManager.archive:
if ArchiveManager.archive.current_scene:
archive_scene = ArchiveManager.archive.current_scene
if ArchiveManager.archive.entrance_portal:
archive_portal = ArchiveManager.archive.entrance_portal
func play_footstep_sound() -> void:
if ground and ground.is_visible_in_tree():
ground.play_footstep_sound()
func transition_to_scene(key: String, portal: String, immediately := false) -> void:
var scene_path = ground_dict[key]
if scene_path:
2024-12-27 13:52:11 +00:00
var scene = load(scene_path).instantiate()
current_scene = key
entrance_portal = portal
2025-01-14 00:56:51 +00:00
# 优先更新 archive使 ground 可以访问自己的 current_scene 键值
_update_archive()
if immediately:
2024-12-27 13:52:11 +00:00
_do_transition(scene)
# 更新玩家位置
2025-01-13 08:09:57 +00:00
if first_entered:
_update_player_position()
else:
var tween = create_tween() as Tween
var player = SceneManager.get_player() as MainPlayer
if player:
player.action_locked = true
#TODO 转场效果
#
2024-12-27 13:52:11 +00:00
tween.tween_interval(0.2)
tween.tween_callback(_do_transition.bind(scene))
2025-01-14 00:56:51 +00:00
if player:
tween.tween_callback(func(): player.action_locked = false)
2025-01-13 08:09:57 +00:00
first_entered = false
else:
print("Scene not found: " + key)
func _update_player_position():
if ignore_archive or Engine.is_editor_hint():
return
var player = SceneManager.get_player() as MainPlayer
if player and ArchiveManager.archive:
# if GlobalConfig.DEBUG:
# print("update player position", ArchiveManager.archive.player_global_position)
player.global_position = ArchiveManager.archive.player_global_position
# fixed y
2025-01-13 08:09:57 +00:00
if ground.player_y_fixed:
player.global_position.y = ground.player_y
player.set_facing_direction(ArchiveManager.archive.player_direction)
2024-12-27 13:52:11 +00:00
func _do_transition(scene: Node2D):
if ground:
# 提前移除,防止命名冲突
remove_child(ground)
2025-01-13 08:09:57 +00:00
ground.queue_free()
ground = scene.get_child(0)
scene.remove_child(ground)
ground.owner = null
2025-01-13 08:09:57 +00:00
scene.queue_free()
add_child(ground)
ground.name = "Ground"
_set_camera_and_player_boundary()
2025-01-14 00:56:51 +00:00
if not Engine.is_editor_hint():
var portal_node = ground.get_node_or_null("DeployLayer/portal_" + entrance_portal) as Node2D
if portal_node:
var player = SceneManager.get_player()
if player:
# player.global_position.x = -20.0
player.global_position.x = portal_node.global_position.x
if GlobalConfig.DEBUG:
print("move player to portal:", entrance_portal, portal_node.global_position)
else:
printerr(current_scene + " portal not found: " + entrance_portal)
if GlobalConfig.DEBUG and not Engine.is_editor_hint():
_watch_scene_update()
func _set_camera_and_player_boundary():
var bg = ground.get_node("BGSprite2D")
2025-01-06 08:06:20 +00:00
# set current_boarder by bg size
if bg.texture and not Engine.is_editor_hint():
var size = bg.texture.get_size() * bg.scale
2025-01-06 08:06:20 +00:00
# camera rect
var camera_size = Vector2(max(564.0, size.x), max(size.y, 316.0))
2025-01-07 10:54:50 +00:00
var camera_upleft = Vector2(0, -camera_size.y / 2.0)
var camera_rect = Rect2(camera_upleft, camera_size)
2025-01-06 08:06:20 +00:00
# player rect should be set centered, with 30px x padding
2025-01-07 10:54:50 +00:00
var up_left = Vector2(0, -size.y / 2.0)
2025-01-06 08:06:20 +00:00
size.x -= 36.0
up_left.x = bg.position.x + 18.0
var player_rect = Rect2(up_left, size)
SceneManager.set_camera_boundary(camera_rect)
SceneManager.set_player_boundary(player_rect)
if GlobalConfig.DEBUG:
print("_set_camera_and_player_boundary:", camera_rect, player_rect)
func _update_archive():
if not Engine.is_editor_hint() and ArchiveManager.archive:
ArchiveManager.archive.current_scene = current_scene
ArchiveManager.archive.entrance_portal = entrance_portal
archive_scene = current_scene
archive_portal = entrance_portal
var update_watcher: Timer
2025-01-14 00:56:51 +00:00
var last_modify_time = 0
2025-01-14 00:56:51 +00:00
# DEBUG 时重新加载资源
func _watch_scene_update():
var scene_path = ground_dict[current_scene]
if scene_path:
2025-01-14 00:56:51 +00:00
last_modify_time = FileAccess.get_modified_time(scene_path)
if not update_watcher:
update_watcher = Timer.new()
update_watcher.wait_time = 1
update_watcher.one_shot = false
add_child(update_watcher)
update_watcher.start()
else:
# remove all connections
for c in update_watcher.timeout.get_connections():
update_watcher.timeout.disconnect(c.callable)
update_watcher.timeout.connect(_check_scene_update.bind(scene_path))
func _check_scene_update(scene_path):
var modify = FileAccess.get_modified_time(scene_path)
2025-01-14 00:56:51 +00:00
if modify != last_modify_time:
last_modify_time = modify
_on_resources_reload(scene_path)
func _on_resources_reload(res):
print("resources_reload processing:", res)
if not Engine.is_editor_hint() and res.ends_with(".tscn"):
ArchiveManager.save_all()
transition_to_scene(current_scene, entrance_portal, true)