import { Color, sp, Tween, tween } from 'cc'; import { SpineBatch } from 'db://assets/resources/multSpines/MultSpine'; /** 闪白峰值:类型 2 + 高插值(见 Mult-spine.effect mixColor) */ const FLASH_PEAK = 2.92; /** 闪白收尾(仍保持类型 2,插值降到近 0) */ const FLASH_TAIL = 2.02; const FLASH_SEC = 0.14; type SkelFlash = sp.Skeleton & { shaderVar: number; _hitFlashProxy?: { v: number } }; /** * Spine 受击闪白(MultSpine shaderVar 类型 2,按 alpha 加权,不白雾透明区)。 * MultSpine 未启用时:短时提亮 tint(不整图铺白),再还原 baseColor。 */ export function playSpineHitFlash(skel: sp.Skeleton | null | undefined, baseColor?: Readonly): void { if (!skel?.isValid) return; const s = skel as SkelFlash; if (!s._hitFlashProxy) s._hitFlashProxy = { v: 0 }; const proxy = s._hitFlashProxy; Tween.stopAllByTarget(proxy); Tween.stopAllByTarget(skel); if (SpineBatch.active() && typeof s.shaderVar === 'number') { proxy.v = FLASH_PEAK; s.shaderVar = FLASH_PEAK; tween(proxy) .to(FLASH_SEC, { v: FLASH_TAIL }, { easing: 'sineOut', onUpdate: () => { if (s.isValid) s.shaderVar = proxy.v; }, }) .call(() => { if (s.isValid) s.shaderVar = 0; }) .start(); return; } // tint 回退:在基准色上短暂提亮,避免 Color.WHITE 铺满网格透明区 const restore = baseColor ? new Color(baseColor.r, baseColor.g, baseColor.b, baseColor.a) : new Color(skel.color.r, skel.color.g, skel.color.b, skel.color.a); const flash = new Color( Math.min(255, restore.r + 120), Math.min(255, restore.g + 120), Math.min(255, restore.b + 120), restore.a, ); skel.color = flash; tween(skel) .delay(FLASH_SEC) .call(() => { if (skel.isValid) skel.color = restore; }) .start(); }