godot-plateformer/_shared/camera/CameraSystem.gd

128 lines
3.0 KiB
GDScript3
Raw Normal View History

2026-01-06 16:19:08 +08:00
'''全局的相机管理器
2026-01-06 11:58:41 +08:00
======= =======
'''
extends Node
var _cached_player_camera: GlobalCamera
var _cached_anchors: Array[CameraAnchor] = []
var _current_anchor: CameraAnchor
var _switch_tween: Tween
## 玩家关卡内静态相机
2026-01-06 16:19:08 +08:00
const PLAYER_CAMERA_SCENE:= preload("res://_shared/camera/PlayerStaticCamera.tscn")
2026-01-06 11:58:41 +08:00
## 注册玩家相机
func register_player_camera(owner: Node) -> GlobalCamera:
if not _cached_player_camera:
_cached_player_camera = PLAYER_CAMERA_SCENE.instantiate() as GlobalCamera
if _cached_player_camera:
owner.add_child(_cached_player_camera)
return _cached_player_camera
## 外部获取玩家全局相机
func get_cached_camera() -> GlobalCamera:
return _cached_player_camera
2026-01-06 23:18:36 +08:00
func get_player_camera() -> GlobalCamera:
return _cached_player_camera
2026-01-06 11:58:41 +08:00
## 注册一个相机锚点
func register_anchor(anchor: CameraAnchor) -> void:
if anchor in _cached_anchors:
return
_cached_anchors.append(anchor)
2026-01-06 16:19:08 +08:00
anchor.on_priority_change.connect(on_anchor_priority_changed)
2026-01-06 11:58:41 +08:00
_sort_anchors()
_try_auto_switch()
2026-01-06 16:19:08 +08:00
## 当相机锚点的权重改变时,向管理器触发事件
func on_anchor_priority_changed(priority:int, anchor: CameraAnchor) -> void:
if _current_anchor:
if _current_anchor._priority < priority:
_sort_anchors()
_try_auto_switch()
2026-01-06 11:58:41 +08:00
## 注销一个相机锚点
func unregister_anchor(anchor: CameraAnchor) -> void:
_cached_anchors.erase(anchor)
if _current_anchor == anchor:
_current_anchor = null
_try_auto_switch()
## 排序已有的锚点
func _sort_anchors() -> void:
_cached_anchors.sort_custom(func(a, b):
2026-01-06 16:19:08 +08:00
return a._priority > b._priority
2026-01-06 11:58:41 +08:00
)
## 尝试自切换
func _try_auto_switch() -> void:
for a in _cached_anchors:
if a.enabled:
switch_anchor(a)
2026-01-06 16:19:08 +08:00
_current_anchor = a
2026-01-06 11:58:41 +08:00
return
2026-01-06 16:19:08 +08:00
## 重置所有的Camera的_priority
2026-01-06 11:58:41 +08:00
func reset_all_camera_priority() -> void:
for a in _cached_anchors:
2026-01-06 16:19:08 +08:00
a._priority = 0
2026-01-06 11:58:41 +08:00
## 切换相机
func switch_anchor(target_anchor: CameraAnchor) -> void:
if target_anchor == null:
return
if target_anchor == _current_anchor:
return
if not is_instance_valid(_cached_player_camera):
return
# 中断旧 Tween
if _switch_tween and _switch_tween.is_running():
_switch_tween.kill()
_switch_tween = null
var camera := _cached_player_camera
var blend_time : float = max(target_anchor.blend_time, 0.001)
# 创建 Tween关键ignore time scale
_switch_tween = get_tree().create_tween()
_switch_tween.set_ignore_time_scale(true)
_switch_tween.set_trans(Tween.TRANS_SINE)
_switch_tween.set_ease(Tween.EASE_OUT)
# ===== 位置 =====
_switch_tween.tween_property(
camera,
2026-01-06 16:19:08 +08:00
"global_position",
2026-01-06 11:58:41 +08:00
target_anchor.global_position,
blend_time
)
# ===== Zoom =====
_switch_tween.tween_property(
camera,
2026-01-06 16:19:08 +08:00
"zoom",
2026-01-06 11:58:41 +08:00
target_anchor.zoom,
blend_time
)
# ===== Offset =====
_switch_tween.tween_property(
camera,
2026-01-06 16:19:08 +08:00
"offset",
2026-01-06 11:58:41 +08:00
target_anchor.offset,
blend_time
)
# 完成回调
_switch_tween.finished.connect(func():
_current_anchor = target_anchor
)
_current_anchor = target_anchor