feat: add cocos-service configuration file feat: add device configuration file feat: add engine configuration file feat: add information configuration file feat: add program configuration file feat: add project configuration file feat: add TypeScript configuration file
408 lines
14 KiB
TypeScript
408 lines
14 KiB
TypeScript
|
|
import { Component, Node, Vec3, tween, Quat, Sprite, Color, math, easing, Camera, ITweenOption, IPunchTweenOption, IShakeTweenOption, Label } from 'cc';
|
|
import { calcPunchData, calcShakeData, quadraticCurve } from './Util';
|
|
|
|
//////////////////////
|
|
// Transform
|
|
//////////////////////
|
|
Node.prototype.qtPosition = function (to: Vec3, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { position: to }, opts);
|
|
}
|
|
|
|
Node.prototype.qtPositionX = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.position;
|
|
return tween(this).to(duration, { position: new Vec3(to, startPos.y, startPos.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtPositionY = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.position;
|
|
return tween(this).to(duration, { position: new Vec3(startPos.x, to, startPos.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtPositionZ = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.position;
|
|
return tween(this).to(duration, { position: new Vec3(startPos.x, startPos.y, to) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtWorldPosition = function (to: Vec3, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { worldPosition: to }, opts);
|
|
}
|
|
|
|
Node.prototype.qtWorldPositionX = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.worldPosition;
|
|
return tween(this).to(duration, { worldPosition: new Vec3(to, startPos.y, startPos.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtWorldPositionY = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.worldPosition;
|
|
return tween(this).to(duration, { worldPosition: new Vec3(startPos.x, to, startPos.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtWorldPositionZ = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startPos = this.worldPosition;
|
|
return tween(this).to(duration, { worldPosition: new Vec3(startPos.x, startPos.y, to) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtRotation = function (to: Vec3, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { eulerAngles: to }, opts);
|
|
}
|
|
|
|
Node.prototype.qtRotationQuat = function (to: Quat, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { rotation: to }, opts);
|
|
}
|
|
|
|
Node.prototype.qtScale = function (to: Vec3 | number, duration: number, opts?: ITweenOption) {
|
|
let toScale = to;
|
|
if (!(to instanceof Vec3)) {
|
|
toScale = new Vec3(to, to, to);
|
|
}
|
|
|
|
return tween(this).to(duration, { scale: toScale }, opts);
|
|
}
|
|
|
|
Node.prototype.qtScaleX = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startScale = this.scale;
|
|
return tween(this).to(duration, { scale: new Vec3(to, startScale.y, startScale.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtScaleY = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startScale = this.scale;
|
|
return tween(this).to(duration, { scale: new Vec3(startScale.x, to, startScale.z) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtScaleZ = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startScale = this.scale;
|
|
return tween(this).to(duration, { scale: new Vec3(startScale.x, startScale.y, to) }, opts);
|
|
}
|
|
|
|
Node.prototype.qtPunchPosition = function (punch: Vec3, duration: number, opts?: IPunchTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 3;
|
|
const elasticity = opts?.elasticity ?? 0.5;
|
|
const { tos, durations } = calcPunchData(this.position.clone(), punch, duration, vibrato, elasticity);
|
|
|
|
const punchTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
punchTween.then(tween().to(d, { position: to }, tweenOpts));
|
|
});
|
|
|
|
return punchTween.union();
|
|
}
|
|
|
|
Node.prototype.qtPunchRotation = function (punch: Vec3, duration: number, opts?: IPunchTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 3;
|
|
const elasticity = opts?.elasticity ?? 0.5;
|
|
const { tos, durations } = calcPunchData(this.rotation.clone(), punch, duration, vibrato, elasticity);
|
|
|
|
const punchTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
punchTween.then(tween().to(d, { eulerAngles: to }, tweenOpts));
|
|
});
|
|
|
|
return punchTween.union();
|
|
}
|
|
|
|
Node.prototype.qtPunchScale = function (punch: Vec3, duration: number, opts?: IPunchTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 3;
|
|
const elasticity = opts?.elasticity ?? 0.5;
|
|
const { tos, durations } = calcPunchData(this.scale.clone(), punch, duration, vibrato, elasticity);
|
|
|
|
const punchTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
punchTween.then(tween().to(d, { scale: to }, tweenOpts));
|
|
});
|
|
|
|
return punchTween.union();
|
|
}
|
|
|
|
Node.prototype.qtJumpPosition = function (to: Vec3, jumpHeight: number, jumpNum: number, duration: number, opts?: ITweenOption) {
|
|
const tweenPos = new Vec3();
|
|
const jumpTween = tween(this);
|
|
const totalNum = jumpNum * 2;
|
|
|
|
// 初始化选项对象,确保即使没有传入选项也不会出错
|
|
const options = opts || {};
|
|
|
|
this.jumpY = 0;
|
|
let startPosY = 0;
|
|
const yUpTween = tween().to(duration / totalNum, { jumpY: jumpHeight }, {
|
|
onStart: (target: Node) => {
|
|
startPosY = target.position.y;
|
|
target.jumpY = 0;
|
|
},
|
|
onUpdate: (target: Node, ratio) => {
|
|
tweenPos.set(target.position);
|
|
tweenPos.y = startPosY + target.jumpY;
|
|
target.position = tweenPos;
|
|
},
|
|
onComplete: (target: Node) => {
|
|
target.jumpY = 0;
|
|
}, easing: 'quadOut'
|
|
}).to(duration / totalNum, { jumpY: jumpHeight }, {
|
|
onStart: (target: Node) => {
|
|
startPosY = target.position.y;
|
|
},
|
|
onUpdate: (target: Node, ratio) => {
|
|
tweenPos.set(target.position);
|
|
tweenPos.y = startPosY - target.jumpY;
|
|
target.position = tweenPos;
|
|
},
|
|
onComplete: (target: Node) => {
|
|
target.jumpY = 0;
|
|
}, easing: 'quadIn',
|
|
}).union().repeat(jumpNum);
|
|
|
|
this.jumpOffsetY = 0;
|
|
let offsetY = 0;
|
|
const offsetYTween = tween().to(duration, { jumpOffsetY: to.y - this.position.y }, {
|
|
onStart: (target: Node) => {
|
|
offsetY = to.y - target.position.y;
|
|
target.jumpOffsetY = 0;
|
|
},
|
|
onUpdate: (target: Node, ratio) => {
|
|
const interpOffsetY = easing.quadOut(ratio) * offsetY;
|
|
tweenPos.set(target.position);
|
|
tweenPos.y += interpOffsetY;
|
|
target.position = tweenPos;
|
|
},
|
|
onComplete: (target: Node) => {
|
|
target.jumpOffsetY = 0;
|
|
}, easing: 'quadOut'
|
|
});
|
|
|
|
this.jumpX = this.position.x;
|
|
this.jumpZ = this.position.z;
|
|
const xzTween = tween().to(duration, { jumpX: to.x, jumpZ: to.z }, {
|
|
// 使用可选链运算符或者默认值
|
|
onStart: options.onStart,
|
|
onUpdate: (target: Node, ratio) => {
|
|
tweenPos.set(target.position);
|
|
tweenPos.x = target.jumpX;
|
|
tweenPos.z = target.jumpZ;
|
|
target.position = tweenPos;
|
|
options.onUpdate?.();
|
|
},
|
|
onComplete: (target: Node) => {
|
|
// delete target.jumpX;
|
|
// delete target.jumpY;
|
|
// delete target.jumpZ;
|
|
// delete target.jumpOffsetY;
|
|
target.jumpX = target.position.x;
|
|
target.jumpZ = target.position.z;
|
|
options.onComplete?.();
|
|
}
|
|
})
|
|
|
|
jumpTween.parallel(yUpTween, offsetYTween, xzTween);
|
|
return jumpTween;
|
|
}
|
|
|
|
Node.prototype.qtShakePosition = function (strength: Vec3 | number, duration: number, opts?: IShakeTweenOption) {
|
|
const options = opts || {};
|
|
|
|
const vibrato = options?.vibrato ?? 10;
|
|
const randomness = options?.randomness ?? 90;
|
|
const fadeOut = options?.fadeOut ?? true;
|
|
let toStrength: Vec3;
|
|
let vectorBased = false;
|
|
if (!(strength instanceof Vec3)) {
|
|
toStrength = new Vec3(strength, strength, strength);
|
|
} else {
|
|
toStrength = strength;
|
|
vectorBased = true;
|
|
}
|
|
const { tos, durations } = calcShakeData(this.position.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut)
|
|
const shakeTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: options.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: options.onComplete
|
|
}
|
|
}
|
|
shakeTween.then(tween().to(d, { position: to }, tweenOpts));
|
|
});
|
|
|
|
return shakeTween.union();
|
|
}
|
|
|
|
Node.prototype.qtShakeRotation = function (strength: Vec3 | number, duration: number, opts?: IShakeTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 10;
|
|
const randomness = opts?.randomness ?? 90;
|
|
const fadeOut = opts?.fadeOut ?? true;
|
|
let toStrength: Vec3;
|
|
let vectorBased = false;
|
|
if (!(strength instanceof Vec3)) {
|
|
toStrength = new Vec3(strength, strength, strength);
|
|
} else {
|
|
toStrength = strength;
|
|
vectorBased = true;
|
|
}
|
|
const { tos, durations } = calcShakeData(this.eulerAngles.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut)
|
|
const shakeTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
shakeTween.then(tween().to(d, { eulerAngles: to }, tweenOpts));
|
|
});
|
|
|
|
return shakeTween.union();
|
|
}
|
|
|
|
Node.prototype.qtShakeScale = function (strength: Vec3 | number, duration: number, opts?: IShakeTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 10;
|
|
const randomness = opts?.randomness ?? 90;
|
|
const fadeOut = opts?.fadeOut ?? true;
|
|
let toStrength: Vec3;
|
|
let vectorBased = false;
|
|
if (!(strength instanceof Vec3)) {
|
|
toStrength = new Vec3(strength, strength, strength);
|
|
} else {
|
|
toStrength = strength;
|
|
vectorBased = true;
|
|
}
|
|
const { tos, durations } = calcShakeData(this.scale.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut)
|
|
const shakeTween = tween(this);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
shakeTween.then(tween().to(d, { scale: to }, tweenOpts));
|
|
});
|
|
|
|
return shakeTween.union();
|
|
}
|
|
|
|
Node.prototype.qtQuadraticCurve = function (p1: Vec3, cp: Vec3, p2: Vec3, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { position: p2, easing: opts?.easing }, {
|
|
onUpdate(target, ratio) {
|
|
target.setPosition(quadraticCurve(ratio, p1, cp, p2));
|
|
},
|
|
onComplete: opts?.onComplete,
|
|
onStart: opts?.onStart
|
|
}).union();
|
|
}
|
|
|
|
//////////////////////
|
|
// Sprite
|
|
//////////////////////
|
|
// good color lerp
|
|
// https://www.alanzucconi.com/2016/01/06/colour-interpolation/
|
|
Sprite.prototype.qtColor = function (to: Color, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { color: to }, opts);
|
|
}
|
|
|
|
Sprite.prototype.qtOpacity = function (to: number, duration: number, opts?: ITweenOption) {
|
|
const startColor = this.color.clone();
|
|
const tempColor = new Color();
|
|
return tween(this).to(duration, { color: new Color(startColor.r, startColor.g, startColor.b, to) }, {
|
|
onStart: opts.onStart,
|
|
onUpdate: (target: { _val: number }, ratio: number) => {
|
|
const lerpA = startColor.a + (to - startColor.a) * ratio
|
|
tempColor.set(startColor.r, startColor.g, startColor.b, lerpA);
|
|
this.color = tempColor;
|
|
opts.onUpdate?.();
|
|
},
|
|
onComplete: opts.onComplete
|
|
});
|
|
}
|
|
|
|
//////////////////////
|
|
// Label
|
|
//////////////////////
|
|
Label.prototype.qtColor = function (to: Color, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { color: to }, opts);
|
|
}
|
|
|
|
Label.prototype.qtString = function (to: string, duration: number, opts?: ITweenOption) {
|
|
return tween(this).to(duration, { string: to }, opts);
|
|
}
|
|
|
|
//////////////////////
|
|
// Camera
|
|
//////////////////////
|
|
Camera.prototype.qtShakePosition = function (strength: Vec3 | number, duration: number, opts?: IShakeTweenOption) {
|
|
const vibrato = opts?.vibrato ?? 10;
|
|
const randomness = opts?.randomness ?? 90;
|
|
const fadeOut = opts?.fadeOut ?? true;
|
|
let toStrength: Vec3;
|
|
let vectorBased = false;
|
|
if (!(strength instanceof Vec3)) {
|
|
toStrength = new Vec3(strength, strength, strength);
|
|
} else {
|
|
toStrength = strength;
|
|
vectorBased = true;
|
|
}
|
|
const { tos, durations } = calcShakeData(this.node.position.clone(), duration, toStrength, vibrato, randomness, true, vectorBased, fadeOut)
|
|
const shakeTween = tween(this.node);
|
|
tos.forEach((to, index) => {
|
|
const d = durations[index];
|
|
let tweenOpts: ITweenOption | undefined;
|
|
if (index === 0) {
|
|
tweenOpts = {
|
|
onStart: opts.onStart
|
|
}
|
|
} else if (index === tos.length - 1) {
|
|
tweenOpts = {
|
|
onComplete: opts.onComplete
|
|
}
|
|
}
|
|
shakeTween.then(tween().to(d, { position: to }, tweenOpts));
|
|
});
|
|
|
|
return shakeTween.union();
|
|
} |