# ScreenHpBar —— 角色头顶的屏幕空间 HP 条(§8.8)。 # # 参考端在 CPythonTextTail / CGraphicTextInstance 的屏幕坐标中绘制尾标; # 这里用一个无输入的 Control 自绘背景、边框和填充,NetWorld 每帧负责把 # 实体的世界坐标投影到屏幕。这样 HP 条不会随 Label3D 的 billboard 深度 # 缩放,也不会被地图几何遮住。 extends Control const DEFAULT_SIZE := Vector2(72.0, 6.0) const MIN_FILL_RATIO := 0.0 const MAX_FILL_RATIO := 1.0 var hp := 0 var max_hp := 0 var ratio := 0.0 var dead := false func _init() -> void: mouse_filter = MOUSE_FILTER_IGNORE size = DEFAULT_SIZE custom_minimum_size = DEFAULT_SIZE func set_vitals(current_hp: int, current_max_hp: int, is_dead: bool) -> void: hp = current_hp max_hp = current_max_hp dead = is_dead ratio = clampf(float(hp) / float(max_hp), MIN_FILL_RATIO, MAX_FILL_RATIO) \ if max_hp > 0 else 0.0 queue_redraw() func _draw() -> void: var r := Rect2(Vector2.ZERO, size) # Dark backing and a one-pixel black border keep the bar legible over terrain. draw_rect(r, Color(0.02, 0.02, 0.025, 0.86), true) var inner := Rect2(Vector2.ONE, Vector2(maxf(0.0, size.x - 2.0), maxf(0.0, size.y - 2.0))) var fill_color := Color(0.35, 0.35, 0.38, 0.95) if dead \ else Color(0.88, 0.14, 0.14, 0.98) inner.size.x *= ratio if inner.size.x > 0.0: draw_rect(inner, fill_color, true) draw_rect(r, Color(0.0, 0.0, 0.0, 0.95), false, 1.0)