feat(client): RMIC::2026 界面重做、可计算的版本机制与固件版本联动
- feat(client): 界面换成墨黑蓝底 + 单支红的矩形语言,切角全部去掉,仅装甲条保留平行四边形 - feat(client): 自托管 HarmonyOS Sans SC 与 JetBrains Mono,中文与拉丁数字逐字回退 - feat(client): 新增启动序列、首启门、用户端 HUD、裁判端控制台、设置抽屉与固件维护页 - feat(client): 裁判端中缝与下方控制台可拖,鼠标落在哪一路下方就看哪一路 - feat(client): 设置抽屉常驻实时预览,与画面共用同一份准星绘制代码 - feat(client): 动效改用 Material 3 的缓动曲线与时长,逐条替换掉自造的贝塞尔 - feat(version): 版本号与 CHANGELOG 由 scripts/version.mjs 从 git 历史算出,不再手写 - feat(firmware): Hello 报文携带语义化版本、构建号与自报协议号,负载向后兼容 - feat(client): 固件版本显示在绑定列表与裁判端每一格;协议不匹配时给出具体原因 - feat(firmware): 固件包版本与客户端同源,都从 version.json 读 - fix(client): getCurrentWindow() 在没有 Tauri 注入时同步抛异常,浏览器预览整棵树被卸载 - fix(client): 启动序列的淡出 effect 清掉了自己刚设的 setTimeout,界面永远停在启动页 - fix(client): 设置抽屉左侧导航的锚点没挂到 section 上,且用错了坐标系 - fix(protocol): Hello 改用宽松帧头解析,让协议不匹配的板子能被解释而不是静默消失 - fix(build): Windows 上 bindgen 加载不了 libclang 的同目录依赖,构建脚本补上搜索路径 - fix(build): esp-idf-sys 在长路径下拒绝构建,固件构建改用短的目标目录 - build(client): 队标图标,含光学尺寸分级与手工拼的多尺寸 ICO - build(ci): 守门 job 增加版本一致性检查,产物名改为 rmic-2026-* - docs: 补充界面语言、版本机制与协议通告布局的说明
This commit is contained in:
@@ -1,11 +1,22 @@
|
||||
/**
|
||||
* 命中反馈的整屏层:闪红 + 顶部一条文字。
|
||||
* 命中反馈的整屏层:边沿泛红 + 条上的读数。
|
||||
*
|
||||
* # 大号数字刻意不放在画面正中
|
||||
*
|
||||
* 第一版把 `-7 / 100 → 93` 放在正中,结果它正好压在瞄准点上——被打中的那一下恰恰是最
|
||||
* 需要看着准星的时候。现在数字由 `VideoSurface` 画在**准星旁边**(跟着瞄准点走,不挡
|
||||
* 目标),这里只留闪红与顶部一条信息。
|
||||
* 目标),这里只留边沿泛红与顶部一条读数。
|
||||
*
|
||||
* # 泛红为什么贴着边沿
|
||||
*
|
||||
* 旧版是一整块径向渐变盖在画面上,等于在最要紧的一瞬间把画面调暗。现在颜色只在四条边上
|
||||
* 用 `inset` 阴影渗进来,中间保持原样——"被打到"这件事从四周传来,而不是挡在眼前。
|
||||
*
|
||||
* # 不给方向
|
||||
*
|
||||
* 命中事件里的 `index` 是**哪一条上报先发现了掉血**,不是"从哪一侧打来的"(主板一次广播
|
||||
* 四条、血值相同,谁先到达取决于 UDP)。把它画成方向箭头会是一条看起来很专业、实际上
|
||||
* 完全错误的线索,比不画糟得多。所以这一层是对称的。
|
||||
*
|
||||
* `key={hit.seq}` 是让 CSS 动画每次都从头开始的关键:同一个元素上换属性不会重启动画,
|
||||
* 于是第二下命中就再也闪不出来了——一个"第一次有效"的 bug。
|
||||
@@ -25,17 +36,26 @@ interface Props {
|
||||
export function HitFlash({ hit, config, relevant, label }: Props) {
|
||||
if (!hit || !relevant || !config.flash) return null;
|
||||
|
||||
const strength = Math.min(0.55, 0.16 * config.intensity);
|
||||
// 强度换算成"边沿渗进来多深"。上限压在 70px:再深就开始吃掉画面。
|
||||
const depth = Math.round(38 + 34 * Math.min(2, Math.max(0.2, config.intensity)));
|
||||
|
||||
return (
|
||||
<div key={hit.seq} className="hit-flash" style={{ ["--flash" as string]: strength }}>
|
||||
<div className="hit-flash__banner">
|
||||
{label && <span className="hit-flash__label">{label}</span>}
|
||||
<span className="hit-flash__value">-{hit.damage}</span>
|
||||
<span className="hit-flash__sub">
|
||||
{hit.from} → {hit.to}
|
||||
<div
|
||||
key={hit.seq}
|
||||
className="hit"
|
||||
style={{ ["--hit-depth" as string]: `${depth}px` }}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<span className="hit__edge" />
|
||||
<span className="hit__tick">
|
||||
{label && <span className="hit__tick-label">{label}</span>}
|
||||
<span className="hit__tick-damage num">−{hit.damage}</span>
|
||||
<span className="hit__tick-hp num">
|
||||
{hit.from}
|
||||
<span className="hit__tick-arrow">→</span>
|
||||
{hit.to}
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user