extends CharacterBody2D # 远程玩家脚本 # 负责处理位置同步和动画播放 # 严格遵循 Visual Only 原则:无输入处理,无物理碰撞 # 公共属性 (snake_case) var user_id: String = "" var target_position: Vector2 = Vector2.ZERO # 内部状态 var last_direction: String = "down" @onready var animation_player: AnimationPlayer = $AnimationPlayer @onready var sprite: Sprite2D = $Sprite2D func _ready(): # 初始化时确保无物理处理 set_physics_process(false) # 初始位置设为当前位置 target_position = global_position # 确保禁用物理碰撞 (双重保险) if has_node("CollisionShape2D"): $CollisionShape2D.disabled = true func _process(delta: float): # 1. 平滑移动插值 var current_pos = global_position var dist = current_pos.distance_to(target_position) if dist > 1.0: # 简单的线性插值,速度系数 10.0 可根据需要调整 var new_pos = current_pos.lerp(target_position, 10.0 * delta) # 计算移动向量用于动画朝向 var move_vec = new_pos - current_pos _update_animation(move_vec) global_position = new_pos else: # 距离很近时直接吸附并播放待机动画 global_position = target_position _play_idle_animation() # 统一初始化方法 # data: 包含 camelCase 字段的字典 (userId, username, position 等) func setup(data: Dictionary): if data.has("userId"): user_id = data.userId if data.has("position"): var pos_data = data.position if pos_data.has("x") and pos_data.has("y"): var new_pos = Vector2(pos_data.x, pos_data.y) global_position = new_pos target_position = new_pos # 如果有名字显示需求,可在此扩展 # if data.has("username") and has_node("Label"): # $Label.text = data.username # 更新目标位置 func update_position(new_pos: Vector2): target_position = new_pos # 动画更新逻辑 (复用 PlayerController 的命名规范) func _update_animation(move_vec: Vector2): if not animation_player: return # 确定主方向 if abs(move_vec.x) > abs(move_vec.y): if move_vec.x > 0: last_direction = "right" else: last_direction = "left" else: if move_vec.y > 0: last_direction = "down" else: last_direction = "up" animation_player.play("walk_" + last_direction) func _play_idle_animation(): if animation_player: animation_player.play("idle_" + last_direction)