extends Node ## 触摸反馈管理器 ## 为移动端提供触摸反馈和优化的触摸体验 # 触摸反馈配置 const HAPTIC_LIGHT = 0.3 const HAPTIC_MEDIUM = 0.6 const HAPTIC_HEAVY = 1.0 const TOUCH_SCALE_FACTOR = 0.95 const TOUCH_FEEDBACK_DURATION = 0.1 # 触摸区域扩展(像素) const TOUCH_AREA_EXPANSION = 20 ## 为按钮添加触摸反馈 func setup_button_feedback(button: Button) -> void: """ 为按钮设置触摸反馈 @param button: 按钮节点 """ if not button: return # 扩展触摸区域 _expand_touch_area(button) # 连接触摸事件 if not button.button_down.is_connected(_on_button_pressed): button.button_down.connect(_on_button_pressed.bind(button)) if not button.button_up.is_connected(_on_button_released): button.button_up.connect(_on_button_released.bind(button)) ## 为输入框添加触摸反馈 func setup_input_feedback(line_edit: LineEdit) -> void: """ 为输入框设置触摸反馈 @param line_edit: 输入框节点 """ if not line_edit: return # 扩展触摸区域 _expand_touch_area(line_edit) # 连接焦点事件 if not line_edit.focus_entered.is_connected(_on_input_focused): line_edit.focus_entered.connect(_on_input_focused.bind(line_edit)) ## 扩展控件的触摸区域 func _expand_touch_area(control: Control) -> void: """ 扩展控件的触摸区域,使其更容易点击 @param control: 控件节点 """ if not control: return # 只在移动设备上扩展触摸区域 if not DisplayServer.is_touchscreen_available(): return # 增加最小尺寸以扩展触摸区域 var current_size = control.custom_minimum_size var expanded_size = Vector2( max(current_size.x, control.size.x + TOUCH_AREA_EXPANSION), max(current_size.y, control.size.y + TOUCH_AREA_EXPANSION) ) control.custom_minimum_size = expanded_size ## 按钮按下反馈 func _on_button_pressed(button: Button) -> void: """ 按钮按下时的反馈 @param button: 按钮节点 """ # 视觉反馈:缩放效果 UIAnimationManager.button_press_feedback(button, TOUCH_SCALE_FACTOR, TOUCH_FEEDBACK_DURATION) # 触觉反馈(如果支持) _trigger_haptic_feedback(HAPTIC_LIGHT) # 音效反馈(可选) _play_touch_sound("button_press") ## 按钮释放反馈 func _on_button_released(button: Button) -> void: """ 按钮释放时的反馈 @param button: 按钮节点 """ # 确保按钮恢复原始大小 if button: var tween = button.create_tween() tween.tween_property(button, "scale", Vector2.ONE, TOUCH_FEEDBACK_DURATION) ## 输入框获得焦点反馈 func _on_input_focused(line_edit: LineEdit) -> void: """ 输入框获得焦点时的反馈 @param line_edit: 输入框节点 """ # 轻微的脉冲效果 UIAnimationManager.pulse_highlight(line_edit, 1.05, 0.4) # 触觉反馈 _trigger_haptic_feedback(HAPTIC_LIGHT) # 音效反馈 _play_touch_sound("input_focus") ## 触发触觉反馈 func _trigger_haptic_feedback(intensity: float) -> void: """ 触发触觉反馈(震动) @param intensity: 震动强度 """ # 检查是否支持触觉反馈 if not DisplayServer.is_touchscreen_available(): return # 在支持的平台上触发震动 if OS.get_name() == "Android": # Android震动 - 在Godot 4中使用Input.vibrate_handheld var duration_ms = int(intensity * 100) # 转换为毫秒 Input.vibrate_handheld(duration_ms) elif OS.get_name() == "iOS": # iOS触觉反馈 - 在Godot 4中也使用Input.vibrate_handheld var duration_ms = int(intensity * 100) Input.vibrate_handheld(duration_ms) ## 播放触摸音效 func _play_touch_sound(_sound_name: String) -> void: """ 播放触摸音效 @param _sound_name: 音效名称(暂未使用,预留给未来的音效系统) """ # 检查是否启用音效 if not preload("res://scripts/GameConfig.gd").get_ui_config().get("enable_sound_effects", true): return # 这里可以添加音效播放逻辑 # 例如:AudioManager.play_ui_sound(_sound_name) pass ## 创建触摸友好的按钮 func create_touch_friendly_button(text: String, size: Vector2 = Vector2(200, 60)) -> Button: """ 创建触摸友好的按钮 @param text: 按钮文本 @param size: 按钮大小 @return: 配置好的按钮 """ var button = Button.new() button.text = text button.custom_minimum_size = size # 设置触摸友好的样式 _apply_touch_friendly_style(button) # 添加触摸反馈 setup_button_feedback(button) return button ## 创建触摸友好的输入框 func create_touch_friendly_input(placeholder: String = "", size: Vector2 = Vector2(300, 50)) -> LineEdit: """ 创建触摸友好的输入框 @param placeholder: 占位符文本 @param size: 输入框大小 @return: 配置好的输入框 """ var input = LineEdit.new() input.placeholder_text = placeholder input.custom_minimum_size = size # 设置触摸友好的样式 _apply_touch_friendly_style(input) # 添加触摸反馈 setup_input_feedback(input) return input ## 应用触摸友好的样式 func _apply_touch_friendly_style(control: Control) -> void: """ 为控件应用触摸友好的样式 @param control: 控件节点 """ if not control: return # 只在移动设备上应用特殊样式 if not DisplayServer.is_touchscreen_available(): return # 增加字体大小以便触摸设备阅读 if control.has_method("add_theme_font_size_override"): control.add_theme_font_size_override("font_size", 18) # 为按钮添加更明显的边框 if control is Button: var style_box = StyleBoxFlat.new() style_box.bg_color = Color(0.2, 0.4, 0.8, 0.8) style_box.border_width_left = 2 style_box.border_width_right = 2 style_box.border_width_top = 2 style_box.border_width_bottom = 2 style_box.border_color = Color(0.3, 0.5, 0.9, 1.0) style_box.corner_radius_top_left = 8 style_box.corner_radius_top_right = 8 style_box.corner_radius_bottom_left = 8 style_box.corner_radius_bottom_right = 8 control.add_theme_stylebox_override("normal", style_box) # 按下状态的样式 var pressed_style = style_box.duplicate() pressed_style.bg_color = Color(0.15, 0.3, 0.6, 0.9) control.add_theme_stylebox_override("pressed", pressed_style) ## 检查是否为移动设备 func is_mobile_device() -> bool: """ 检查当前是否为移动设备 @return: 是否为移动设备 """ var os_name = OS.get_name() return os_name in ["Android", "iOS"] or DisplayServer.is_touchscreen_available() ## 获取推荐的触摸目标大小 func get_recommended_touch_size() -> Vector2: """ 获取推荐的触摸目标大小 @return: 推荐的最小触摸大小 """ if is_mobile_device(): return Vector2(60, 60) # 移动设备推荐最小44-60像素 else: return Vector2(40, 40) # 桌面设备可以更小 ## 自动优化界面的触摸体验 func optimize_ui_for_touch(root_node: Control) -> void: """ 自动优化界面的触摸体验 @param root_node: 根节点 """ if not is_mobile_device(): return _optimize_node_recursive(root_node) ## 递归优化节点 func _optimize_node_recursive(node: Node) -> void: """ 递归优化节点的触摸体验 @param node: 节点 """ if node is Button: setup_button_feedback(node as Button) _apply_touch_friendly_style(node as Control) elif node is LineEdit: setup_input_feedback(node as LineEdit) _apply_touch_friendly_style(node as Control) # 递归处理子节点 for child in node.get_children(): _optimize_node_recursive(child)