Files
go-a-dot/camera_2d.gd

78 lines
2.4 KiB
GDScript

extends Camera2D
@export var smoothing_enabled_custom: bool = true
@export var margin: Vector2 = Vector2(0, 0)
@export var min_zoom: float = 0.1
@export var max_zoom: float = 5.0
@export var transition_duration: float = 0.8
var _tween: Tween
func transition_to_bounds(bounds: Rect2) -> void:
# 1. 计算目标数据
var target_zoom_val = _calculate_zoom_for_bounds(bounds)
var target_zoom = Vector2(target_zoom_val, target_zoom_val)
var target_position = bounds.get_center()
print("[Camera2D] Transition start -> Pos: ", target_position, " Zoom: ", target_zoom)
# 2. 准备过渡
if _tween: _tween.kill()
_tween = create_tween()
_tween.set_parallel(true)
_tween.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN_OUT)
# 暂时禁用内置平滑和限制,避免冲突
var prev_smoothing = position_smoothing_enabled
position_smoothing_enabled = false
_clear_limits()
# 3. 执行过渡
_tween.tween_property(self, "zoom", target_zoom, transition_duration)
_tween.tween_property(self, "global_position", target_position, transition_duration)
# 4. 过渡完成回调
_tween.chain().tween_callback(func():
print("[Camera2D] Transition done.")
set_bounds_limit(bounds)
# 恢复平滑设置 (如果之前开启了)
if prev_smoothing:
position_smoothing_enabled = true
# 也可以强制启用,看你需求
# position_smoothing_enabled = smoothing_enabled_custom
)
func _calculate_zoom_for_bounds(bounds: Rect2) -> float:
var viewport_rect = get_viewport_rect()
var viewport_size = viewport_rect.size
var target_size = bounds.size + margin * 2
if target_size.x <= 0 or target_size.y <= 0:
return zoom.x
var scale_x = viewport_size.x / target_size.x
var scale_y = viewport_size.y / target_size.y
var new_zoom = min(scale_x, scale_y)
return clamp(new_zoom, min_zoom, max_zoom)
# 立即设置(非过渡)
func fit_to_bounds(bounds: Rect2) -> void:
var new_zoom_val = _calculate_zoom_for_bounds(bounds)
zoom = Vector2(new_zoom_val, new_zoom_val)
func center_on_bounds(bounds: Rect2) -> void:
global_position = bounds.get_center()
func set_bounds_limit(bounds: Rect2) -> void:
limit_left = int(bounds.position.x)
limit_right = int(bounds.end.x)
limit_top = int(bounds.position.y)
limit_bottom = int(bounds.end.y)
func _clear_limits() -> void:
limit_left = -10000000
limit_right = 10000000
limit_top = -10000000
limit_bottom = 10000000