Files
whale-town/scripts/DebugCamera.gd
2025-12-05 19:00:14 +08:00

211 lines
6.9 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends Camera2D
## 调试相机控制
## 用于在测试场景时移动相机查看不同区域
# 相机移动速度
var move_speed = 500.0
var zoom_speed = 1.2 # 大幅增加缩放速度让Q/E响应更快
# 最小和最大缩放
var min_zoom = 0.3
var max_zoom = 2.0
# 重置动画相关
var is_resetting = false
var reset_target_position = Vector2.ZERO
var reset_target_zoom = Vector2.ONE
var reset_duration = 1.2 # 进一步增加重置动画时间,让动画更慢更优雅
# 流畅滚轮缩放相关
var scroll_velocity = 0.0 # 当前滚轮速度
var scroll_acceleration = 0.0 # 滚轮加速度
var scroll_friction = 8.0 # 摩擦力,控制减速
var scroll_sensitivity = 0.8 # 滚轮敏感度
var max_scroll_speed = 3.0 # 最大滚轮速度
var zoom_smoothness = 12.0 # 缩放平滑度
var current_target_zoom = 1.0 # 当前目标缩放值
# UI状态检测
var ui_focused = false
func _ready():
print("Debug Camera Controls:")
print(" WASD / Arrow Keys - Move camera")
print(" Mouse Wheel - Zoom in/out (smooth)")
print(" R - Reset camera position")
# 初始化目标缩放值
current_target_zoom = zoom.x
func _process(delta):
# 如果正在重置,跳过手动控制
if is_resetting:
return
# 检查UI焦点状态
_update_ui_focus_status()
# 处理流畅滚轮缩放
_update_smooth_zoom(delta)
# 相机移动只有在UI未获得焦点时
var move_direction = Vector2.ZERO
if not ui_focused:
# WASD 或方向键移动
if Input.is_action_pressed("ui_right") or Input.is_key_pressed(KEY_D):
move_direction.x += 1
if Input.is_action_pressed("ui_left") or Input.is_key_pressed(KEY_A):
move_direction.x -= 1
if Input.is_action_pressed("ui_down") or Input.is_key_pressed(KEY_S):
move_direction.y += 1
if Input.is_action_pressed("ui_up") or Input.is_key_pressed(KEY_W):
move_direction.y -= 1
# 重置相机
if Input.is_action_just_pressed("ui_accept") or Input.is_key_pressed(KEY_R):
reset_camera_smooth()
# 应用移动
if move_direction.length() > 0:
move_direction = move_direction.normalized()
position += move_direction * move_speed * delta
func _input(event):
# 流畅鼠标滚轮缩放
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
_add_scroll_impulse(scroll_sensitivity)
elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
_add_scroll_impulse(-scroll_sensitivity)
func zoom_camera(amount: float):
"""缩放相机(平滑缩放,避免颠簸)"""
var new_zoom = zoom.x + amount
new_zoom = clamp(new_zoom, min_zoom, max_zoom)
# 使用短暂的平滑动画来避免突兀的缩放
var tween = create_tween()
tween.tween_property(self, "zoom", Vector2(new_zoom, new_zoom), 0.05)
tween.set_ease(Tween.EASE_OUT)
tween.set_trans(Tween.TRANS_QUART)
func _add_scroll_impulse(impulse: float):
"""添加滚轮冲量,实现流畅缩放"""
# 根据滚轮滑动距离调整速度(滑动越远,速度越快)
var speed_multiplier = abs(impulse) * 1.5 + 1.0
scroll_velocity += impulse * speed_multiplier
# 限制最大滚轮速度
scroll_velocity = clamp(scroll_velocity, -max_scroll_speed, max_scroll_speed)
func _update_smooth_zoom(delta: float):
"""更新流畅缩放效果"""
# 如果有滚轮速度,更新目标缩放值
if abs(scroll_velocity) > 0.01:
# 根据速度更新目标缩放
var zoom_change = scroll_velocity * delta * 2.0
current_target_zoom += zoom_change
current_target_zoom = clamp(current_target_zoom, min_zoom, max_zoom)
# 应用摩擦力减速
scroll_velocity = lerp(scroll_velocity, 0.0, scroll_friction * delta)
else:
# 速度很小时直接停止
scroll_velocity = 0.0
# 平滑插值到目标缩放值
var current_zoom = zoom.x
var new_zoom = lerp(current_zoom, current_target_zoom, zoom_smoothness * delta)
# 只有当缩放值有明显变化时才更新
if abs(new_zoom - current_zoom) > 0.001:
zoom = Vector2(new_zoom, new_zoom)
func reset_camera():
"""重置相机到初始位置(立即)"""
position = Vector2(640, 360)
zoom = Vector2(1.0, 1.0)
current_target_zoom = 1.0
scroll_velocity = 0.0
print("Camera reset to default position")
func reset_camera_smooth():
"""平滑重置相机到初始位置"""
if is_resetting:
return # 如果已经在重置中,忽略
# 检查是否有跟随的角色
var player_character = _find_player_character()
if player_character:
# 如果有玩家角色,重置到角色位置
reset_target_position = player_character.global_position
print("Resetting camera to player position: ", reset_target_position)
else:
# 否则重置到默认位置
reset_target_position = Vector2(640, 360)
print("Resetting camera to default position: ", reset_target_position)
reset_target_zoom = Vector2(1.0, 1.0)
# 创建平滑动画
is_resetting = true
var tween = create_tween()
tween.set_parallel(true) # 允许同时进行位置和缩放动画
# 位置动画 - 使用更平滑的缓动效果
var position_tween = tween.tween_property(self, "position", reset_target_position, reset_duration)
position_tween.set_ease(Tween.EASE_OUT) # 开始快,结束慢,更自然
position_tween.set_trans(Tween.TRANS_CUBIC) # 使用三次方过渡,更平滑
# 缩放动画 - 同样使用平滑缓动效果
var zoom_tween = tween.tween_property(self, "zoom", reset_target_zoom, reset_duration)
zoom_tween.set_ease(Tween.EASE_OUT) # 开始快,结束慢,更自然
zoom_tween.set_trans(Tween.TRANS_CUBIC) # 使用三次方过渡,更平滑
# 动画完成后的回调
tween.finished.connect(_on_reset_finished)
func _on_reset_finished():
"""重置动画完成回调"""
is_resetting = false
current_target_zoom = reset_target_zoom.x
scroll_velocity = 0.0
print("Camera reset animation completed")
func _update_ui_focus_status():
"""更新UI焦点状态"""
ui_focused = _is_ui_focused()
func _is_ui_focused() -> bool:
"""
检查是否有UI控件获得焦点如输入框
@return: 是否有UI控件获得焦点
"""
var focused_control = get_viewport().gui_get_focus_owner()
# 如果有控件获得焦点且是输入类控件则认为UI处于活动状态
if focused_control:
return focused_control is LineEdit or focused_control is TextEdit
return false
func _find_player_character() -> Node2D:
"""查找玩家角色"""
# 尝试从场景树中找到玩家角色
var main_scene = get_tree().root.get_node_or_null("Main")
if main_scene:
# 查找 GameWorld 下的角色
var game_world = main_scene.get_node_or_null("GameWorld")
if game_world:
# 查找 DatawhaleOffice 场景
var office_scene = game_world.get_child(0) if game_world.get_child_count() > 0 else null
if office_scene:
# 查找 Characters 容器
var characters_container = office_scene.get_node_or_null("Characters")
if characters_container and characters_container.get_child_count() > 0:
# 返回第一个角色(通常是玩家)
return characters_container.get_child(0)
return null