gohud

HUD

← 控件

好不好看,是小地方决定的

大面板再怎么打磨,真正扎眼的永远是某个小东西:一个词被劈成两截、一圈辉光被切掉、一个挤得慌的快捷槽。 2026-09-13 有人指出了四处这样的问题,修复落在控件和主题里,而不是演示界面上, 这样每一个界面都能得到同样的结果。

看到的现象原因修法
引导标记的 Done 变成了 Don/e 开启换行的按钮会把文字宽度从自己的最小宽度里减掉 —— 一挤就会从词中间断开 GoStyle.fit_words():单个词永不换行;多个词可以换行,但最长的那个词始终放得下 —— 判断依据是实际显示的文字而不是翻译键,并且语言切换时表单会重新应用一次
通栏按钮左侧的辉光被竖着切掉了 滚动容器一律在自己的边界处裁剪,没有例外。只有右侧因为滚动条留出的空隙才幸存下来 GoScroll 借用父级的内边距,把自己的边界往外推 12dp,再在内部还回去 —— 内容位置不变
快捷槽里的时间、图标和数量竖着堆成一摞 48dp 里塞了三行 图标放大居中,快捷键放左上角,数量做成右下角的角标,剩余时间做成压在图标上的角标 —— 角标面板来自皮肤的 badge_box()
下拉菜单一片扁平,看不出选中了哪一项 选项悬停用的是按钮面板;单选标记用的是引擎那个极淡的默认样式 专门的悬停面板(柔和的强调色底)、与复选框同款的单选图形,以及按触摸尺寸设定的选项高度
展开的下拉菜单 —— 柔和的强调色悬停面板和选中项的单选标记
下拉菜单 —— 悬停面板与单选标记
四个快捷槽 —— 左上角是快捷键,右下角是数量角标,第一个还带剩余时间角标
快捷槽 —— 角标与剩余时间(科幻)

给纯图标按钮加一段描述:GoStyle.icon_button(icon, action, -1, tooltip_key) —— 给鼠标用户看的工具提示,和给读屏软件用的无障碍名称,都来自这同一个值。 工具提示由 gohud 自己绘制:引擎的默认实现在宽度计算出错时会把文字拆成一行一个字(实测宽度只有 1dp)。

引导卡片会避开固定部件

横屏时,这张卡片以前会被推到最上边或最下边 —— 而那正是页眉和 HUD 部件所在的位置; 在演示里它就正好压在了页眉的 → × 上。现在它会与目标保持齐平, 绕开任何会预留空间的 GoHudAnchor,还能通过 keep_clear 接收其他需要避开的东西。它以能让开障碍物又不遮住目标的最短距离移动, 屏幕小到无论如何都躲不开时就待在原地 —— 挡住一点也好过整个消失。 它的立体感 —— 让人一眼看出它浮在页面之上 —— 来自皮肤旋钮 (float_shadow_sizefloat_shadow_liftfloat_shadow_alpha;切角皮肤用的是 float_glow_size)。

tour.keep_clear = [header_bar, toolbar]   # 不是锚点的那些固定部件

有鼠标和键盘的屏幕

手指没有悬停状态。 只照着移动端做,就会有两种只在桌面出现的状态没人检查 —— 其中一种当时确实是坏的:gohud 的焦点框在主按钮上根本看不见。 面板是强调色,焦点框也是强调色:1.00:1,等于用同一种颜色画在自己身上。 用键盘移动时,完全看不出焦点在哪里。

同一排按钮的三种状态 —— 常态、鼠标悬停、键盘焦点
从上到下:常态 · 悬停 · 焦点。实心按钮的焦点框会与自身面板形成对比。

实心按钮(GoPrimaryButtonGoDangerSolidButton)使用与自身面板形成对比的焦点框 —— 深色主题上用深色,浅色主题上用白色,科幻风格下是一副深色瞄准框。对比度检查器测的是 焦点框与它所在的面板,所以换一套调色板这条规则依然成立(WCAG 2.4.11 要求焦点指示器达到 3:1)。

HUD 控件

GoHudAnchor —— 九个位置

它会尊重安全区域和边缘留白。给它一个 landscape_spot,横屏时它就会换位置 —— 竖屏时待在底部居中的操控件,横屏可以改到右下角。

它为什么存在。 逐个 HUD 部件手写锚点和偏移,迟早会跑偏:生命条跑到刘海屏的摄像头开孔底下, 操控按钮在横屏时压上手势条。这些算术统一放在一个地方。

别让内容钻到 HUD 底下

当一个可滚动的界面和 HUD 共用屏幕时,内容会从 HUD 底下滑过去,两组文字叠在一起, 最后哪一组都读不出来。这在本插件里发生过两次:输入框的占位文字从快捷槽之间挤了出来, 设置项开关的滑块落在了生命条上。

form.avoid_hud = true                  # 避开每一个可见的 GoHudAnchor
joystick_anchor.reserve_space = false  # …只在手指按下时才出现的那些除外

每个矩形都朝着损失面积最小的方向避让。右上角的一根状态条,在竖屏手机上是往下绕(占高度的 13%), 横屏时则往侧边绕(占宽度的 21%)—— 横屏时若竖着避让要付出屏幕的 27%。 已经让出去的地盘会先扣掉,再去测量下一个矩形。

HUD 部件之间也会打架

九个位置把屏幕分好了,却不保证各个部件互不相撞。顶部居中的一条宽消息条, 结结实实地压在了右上角的生命条上,把数值挡住了 —— 你根本看不出还剩多少血。

notice_anchor.avoid_peers = true      # 落到固定 HUD 的下方
notice_anchor.reserve_space = false   # 而且它显示时不会把页面顶开

只在竖直方向让位 —— 要是连横向也动,居中的提示条每次出现的位置都不一样。 而且它只避开那些不会自己让位的部件:两边都让,就会永远交换位置换个不停。

GoBar —— 生命、魔法、经验

var hp := GoBar.new()
hp.label_text = "HP"
hp.ink = GoUi.color(GoTheme.DANGER_FILL)   # 仅用于填充的令牌
hp.set_values(320, 500)                     # "320 / 500"

数值变化会在 0.18 秒内缓动 —— 一根直接跳过去的生命条,没法让你感觉到这一下有多重。 reduce_motion 会让它瞬间完成。大数字会缩写成 12.3k, 这样位数增减时状态条的宽度不会抖来抖去。

GoSlot —— 一个快捷槽

图标、数量、冷却和快捷键都在同一个面上。把角标挂在一个小圆圈外面, 会让每个槽宽度都不一样,整排跟着晃。

看得见的大小和能按到的大小不是一回事。 排得紧密的快捷槽,48dp 的触摸区会互相重叠; 重叠部分归中心更近的那个槽 —— 用 touch_peers 让它们互相知道彼此的存在。

keyboard_focus 默认关闭,这样一排八个快捷槽就不会横在键盘用户和后面每一个设置控件之间的 Tab 顺序里。 只有键盘或手柄可用时再把它打开。

GoJoystick —— 虚拟摇杆

模式行为
FIXED永远在同一个位置 —— 不用看也能摸到
FOLLOW拇指按在哪儿它就出现在哪儿
RELATIVE出现之后继续跟着拇指走 —— 长时间移动更省力

moved 传出的 Vector2 长度在 0–1 之间,可以直接乘到速度上; 它不随屏幕尺寸或 DPI 变化。

GoIconButton —— 看着小,按着大

只有在相邻控件不接收输入时才安全。 如果扩大后的区域盖住了下一个按钮, 那个按钮就会失去响应。并排的图标按钮需要 touch_peers