You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/script/battle/view/HitLeanBack.ts

65 lines
2.1 KiB

3 weeks ago
import { Node, Tween, tween } from 'cc';
type LeanProxy = { angle: number; sx: number; sy: number };
const PROXY_KEY = '_hitLeanProxy';
/**
* 受击后仰(搞笑向):按来击反方向旋转后仰 + 压扁/拉伸。
* hitDir = 击退方向(目标 - 来源),单位任意。
* 注:部分运行时无 UISkew,故用 angle 表达斜切感。
*/
export function playHitLeanBack(target: Node, hitDirX: number, hitDirY = 0): void {
if (!target?.isValid) return;
const len = Math.hypot(hitDirX, hitDirY);
let nx = len > 1e-3 ? hitDirX / len : 0;
let ny = len > 1e-3 ? hitDirY / len : 0;
if (Math.abs(nx) < 0.08 && Math.abs(ny) < 0.08) {
nx = 1;
ny = 0;
}
// 击退向右 → 身体顺时针后仰(负 angle 在 2D UI 常见朝向需实测;取 -nx)
const peakAngle = -nx * (18 + Math.abs(nx) * 10); // 约 ±18°~28°
const squashX = 1.22 + Math.abs(nx) * 0.08;
const squashY = 0.68 - Math.abs(ny) * 0.06;
const stretchX = 0.86;
const stretchY = 1.18;
const old = (target as Node & { [PROXY_KEY]?: LeanProxy })[PROXY_KEY];
if (old) Tween.stopAllByTarget(old);
Tween.stopAllByTarget(target);
const proxy: LeanProxy = { angle: 0, sx: 1, sy: 1 };
(target as Node & { [PROXY_KEY]?: LeanProxy })[PROXY_KEY] = proxy;
target.angle = 0;
target.setScale(1, 1, 1);
const apply = (): void => {
if (!target.isValid) return;
target.angle = proxy.angle;
target.setScale(proxy.sx, proxy.sy, 1);
};
tween(proxy)
.to(0.045, { angle: peakAngle * 0.4, sx: squashX, sy: squashY }, {
easing: 'quadOut',
onUpdate: apply,
})
.to(0.09, { angle: peakAngle, sx: stretchX, sy: stretchY }, {
easing: 'backOut',
onUpdate: apply,
})
.to(0.18, { angle: 0, sx: 1, sy: 1 }, {
easing: 'elasticOut',
onUpdate: apply,
})
.call(() => {
if (!target.isValid) return;
target.angle = 0;
target.setScale(1, 1, 1);
})
.start();
}