extends CharacterBody2D class_name Val # 移动速度 @export var speed: float = 100.0 # 节点引用 @onready var body_placeholder: ColorRect = $BodyPlaceholder @onready var head_placeholder: ColorRect = $HeadPlaceholder @onready var thought_bubble: Label = $ThoughtBubble @onready var state_indicator: Label = $StateIndicator @onready var nav_agent: NavigationAgent2D = $NavigationAgent2D @onready var interaction_timer: Timer = $InteractionTimer @onready var think_timer: Timer = $ThinkTimer # 状态 enum State { IDLE, WALK, INTERACT, THINK } var current_state: State = State.IDLE var current_room: String = "客厅" var agent_state: Dictionary = { "location": "客厅", "energy": 80, "mood": "开心", "activity": "idle" } # 目标 var target_position: Vector2 = Vector2.ZERO var target_furniture: Node = null var bridge: Node = null # 动画颜色 var normal_color = Color(0.36, 0.61, 0.84, 1) # 蓝色 var interact_color = Color(0.5, 0.8, 0.36, 1) # 绿色 var think_color = Color(0.8, 0.5, 0.36, 1) # 橙色 signal state_changed(new_state: String) signal action_completed(action: String) func _ready(): # 初始化 thought_bubble.hide() update_state_display() # 连接导航完成信号 nav_agent.navigation_finished.connect(_on_navigation_finished) # 查找 BridgeClient _find_bridge() print("Val ready at position: ", global_position) func _find_bridge(): # 尝试多种路径 bridge = get_node_or_null("../../BridgeClient") if not bridge: bridge = get_node_or_null("/root/Main/BridgeClient") if not bridge: await get_tree().process_frame bridge = get_node_or_null("../../BridgeClient") if bridge: print("Val: BridgeClient found") if bridge.has_signal("action_received"): bridge.action_received.connect(_on_bridge_action) if bridge.has_signal("state_synced"): bridge.state_synced.connect(_on_state_synced) else: print("Val: BridgeClient not found - running in standalone mode") func _physics_process(delta): match current_state: State.WALK: _handle_walk(delta) State.INTERACT: _handle_interact() State.THINK: _handle_think() _: _handle_idle() func _handle_walk(delta): if nav_agent.is_navigation_finished(): current_state = State.IDLE update_state_display() emit_signal("action_completed", "walk") return var next_pos = nav_agent.get_next_path_position() var direction = (next_pos - global_position).normalized() velocity = direction * speed # 翻转精灵 if direction.x < 0: body_placeholder.scale.x = -1 head_placeholder.scale.x = -1 elif direction.x > 0: body_placeholder.scale.x = 1 head_placeholder.scale.x = 1 # 行走时颜色闪烁 body_placeholder.color = normal_color.lerp(Color.WHITE, sin(Time.get_ticks_msec() * 0.01) * 0.1) move_and_slide() func _handle_idle(): velocity = Vector2.ZERO body_placeholder.color = normal_color head_placeholder.color = normal_color state_indicator.text = "idle" func _handle_interact(): velocity = Vector2.ZERO body_placeholder.color = interact_color head_placeholder.color = interact_color state_indicator.text = "interact" func _handle_think(): velocity = Vector2.ZERO body_placeholder.color = think_color head_placeholder.color = think_color state_indicator.text = "think" # 移动到指定位置 func move_to(pos: Vector2): target_position = pos nav_agent.target_position = pos current_state = State.WALK update_state_display() emit_signal("state_changed", "walk") print("Val moving to: ", pos) # 移动到家具并交互 func interact_with(furniture: Node): target_furniture = furniture var interact_pos = furniture.global_position + Vector2(0, 60) print("Val will interact with: ", furniture.get_meta("furniture_name", "未知"), " at ", interact_pos) move_to(interact_pos) # 等待移动完成后再交互 await action_completed _start_interaction(furniture) func _start_interaction(furniture: Node): current_state = State.INTERACT update_state_display() var furniture_name = furniture.get_meta("furniture_name", "物品") var interaction = furniture.get_meta("interaction", "使用") show_thought("正在" + interaction + furniture_name + "...") # 发送交互事件到Bridge _send_to_bridge({ "type": "furniture_interacted", "furniture": furniture_name, "interaction": interaction, "position": [global_position.x, global_position.y] }) # 交互持续2秒 interaction_timer.start(2.0) await interaction_timer.timeout current_state = State.IDLE thought_bubble.hide() update_state_display() emit_signal("action_completed", "interact") print("Val finished interacting with: ", furniture_name) # 显示思考气泡 func show_thought(text: String, duration: float = 3.0): thought_bubble.text = text thought_bubble.show() if duration > 0: think_timer.start(duration) await think_timer.timeout thought_bubble.hide() # 处理Bridge发来的动作 func _on_bridge_action(action: Dictionary): match action.get("cmd", ""): "walk_to": move_to(Vector2(action.pos[0], action.pos[1])) "show_thought": show_thought(action.get("text", ""), action.get("duration", 3.0)) "interact": var furniture_path = action.get("furniture_path", "") if furniture_path: var furniture = get_node_or_null(furniture_path) if furniture: interact_with(furniture) "update_state": _update_internal_state(action.get("key", ""), action.get("value")) # 同步OpenClaw状态 func _on_state_synced(state: Dictionary): agent_state = state current_room = state.get("location", current_room) update_state_display() func _update_internal_state(key: String, value): agent_state[key] = value update_state_display() func update_state_display(): state_indicator.text = State.keys()[current_state].to_lower() func _on_navigation_finished(): current_state = State.IDLE update_state_display() print("Val navigation finished") func _send_to_bridge(data: Dictionary): if bridge and "send_command" in bridge: bridge.send_command(data) # 公共API:接收用户指令 func receive_command(command: String): show_thought("思考中...", 0) current_state = State.THINK update_state_display() _send_to_bridge({ "type": "user_command", "command": command, "current_state": agent_state })