extends Control class_name VirtualJoystick ## 虚拟摇杆控件 ## 用于移动端触摸输入 # 摇杆参数 @export var joystick_radius: float = 50.0 @export var stick_radius: float = 20.0 @export var dead_zone: float = 0.2 # 摇杆状态 var is_pressed: bool = false var touch_index: int = -1 var stick_position: Vector2 = Vector2.ZERO var output_direction: Vector2 = Vector2.ZERO # 视觉元素 var base_circle: ColorRect var stick_circle: ColorRect func _ready(): """初始化虚拟摇杆""" _create_visual_elements() # 设置大小 custom_minimum_size = Vector2(joystick_radius * 2, joystick_radius * 2) size = custom_minimum_size func _create_visual_elements(): """创建摇杆的视觉元素""" # 创建底座 base_circle = ColorRect.new() base_circle.color = Color(0.3, 0.3, 0.3, 0.5) base_circle.size = Vector2(joystick_radius * 2, joystick_radius * 2) base_circle.position = Vector2.ZERO add_child(base_circle) # 创建摇杆 stick_circle = ColorRect.new() stick_circle.color = Color(0.8, 0.8, 0.8, 0.8) stick_circle.size = Vector2(stick_radius * 2, stick_radius * 2) stick_circle.position = Vector2(joystick_radius - stick_radius, joystick_radius - stick_radius) add_child(stick_circle) func _gui_input(event: InputEvent): """处理触摸输入""" if event is InputEventScreenTouch: if event.pressed: # 触摸开始 is_pressed = true touch_index = event.index _update_stick_position(event.position) elif event.index == touch_index: # 触摸结束 is_pressed = false touch_index = -1 _reset_stick() elif event is InputEventScreenDrag and event.index == touch_index: # 触摸拖动 _update_stick_position(event.position) func _update_stick_position(touch_pos: Vector2): """更新摇杆位置""" var center = Vector2(joystick_radius, joystick_radius) var offset = touch_pos - center # 限制在摇杆范围内 var max_distance = joystick_radius - stick_radius if offset.length() > max_distance: offset = offset.normalized() * max_distance stick_position = offset # 更新视觉位置 stick_circle.position = center + offset - Vector2(stick_radius, stick_radius) # 计算输出方向 var normalized_offset = offset / max_distance if normalized_offset.length() < dead_zone: output_direction = Vector2.ZERO else: output_direction = normalized_offset.normalized() * ((normalized_offset.length() - dead_zone) / (1.0 - dead_zone)) func _reset_stick(): """重置摇杆到中心""" stick_position = Vector2.ZERO output_direction = Vector2.ZERO var center = Vector2(joystick_radius, joystick_radius) stick_circle.position = center - Vector2(stick_radius, stick_radius) ## 获取当前方向 func get_direction() -> Vector2: """ 获取摇杆当前方向 @return: 归一化的方向向量 """ return output_direction