创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

210
scripts/DebugCamera.gd Normal file
View File

@@ -0,0 +1,210 @@
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