├── .gitignore ├── README.md ├── assets ├── QuickTween.meta ├── QuickTween │ ├── QuickTween.ts │ ├── QuickTween.ts.meta │ ├── Util.ts │ ├── Util.ts.meta │ ├── quick-tween.d.ts │ └── quick-tween.d.ts.meta ├── Scenes.meta ├── Scenes │ ├── TestJump.scene │ └── TestJump.scene.meta ├── Scripts.meta └── Scripts │ ├── TestJump.ts │ └── TestJump.ts.meta ├── imgs ├── jump.gif ├── punch_scale.gif └── shake_rotation.gif ├── package.json ├── settings └── v2 │ └── packages │ ├── builder.json │ ├── cocos-service.json │ ├── device.json │ ├── engine.json │ ├── program.json │ └── project.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #/////////////////////////// 3 | # Cocos Creator Project 4 | #/////////////////////////// 5 | library/ 6 | temp/ 7 | local/ 8 | build/ 9 | profiles/ 10 | native 11 | #////////////////////////// 12 | # NPM 13 | #////////////////////////// 14 | node_modules/ 15 | 16 | #////////////////////////// 17 | # VSCode 18 | #////////////////////////// 19 | .vscode/ 20 | 21 | #////////////////////////// 22 | # WebStorm 23 | #////////////////////////// 24 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickTween 2 | 简化CocosCreator中Tween的使用流程。参考了[DOTWeen](http://dotween.demigiant.com/index.php)。 3 | 4 | ## 更便利的创建tween 5 | 直接在相关对象的原型上polyfill了tween的创建 6 | 7 | 内置方式: 8 | ```ts 9 | cc.tween(node).to(1, { position: new Vec(0, 3, 0)}).start(); 10 | ``` 11 | 12 | 使用QuickTween: 13 | ```ts 14 | node.qtPosition(new Vec3(0, 3, 0), 1).start(); 15 | ``` 16 | 17 | ## 增加一些常用的组合Tween 18 | 19 | 例如: 20 | 21 | ### `qtJumpPosition` 22 | 用于从一个位置跳到另一个位置 23 | ```ts 24 | node.qtJumpPosition(new Vec3(3, 1, 0), 3, 1, 1).start(); 25 | ``` 26 | 27 | !['jump'](./imgs/jump.gif) 28 | 29 | ### `qtPunchScale` 30 | 用于对目标施加一个力,产生来回弹的效果 31 | ```ts 32 | node.qtPunchScale(new Vec3(1, 1, 1), 1).start(); 33 | ``` 34 | 35 | !['punch scale'](./imgs/punch_scale.gif) 36 | 37 | ### `qtShakeRotation` 38 | 用于对目标的旋转产生一个抖动效果 39 | ```ts 40 | node.qtPunchScale(new Vec3(1, 1, 1), 1).start(); 41 | ``` 42 | 43 | !['shake rotation'](./imgs/shake_rotation.gif) 44 | 45 | ## 使用方式 46 | 将QuickTween文件夹复制到项目的任意文件夹下,就可以使用了。 -------------------------------------------------------------------------------- /assets/QuickTween.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "795c004d-3684-427a-9853-91a05c52355e", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /assets/QuickTween/QuickTween.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Component, Node, Vec3, tween, Quat, Sprite, Color, math, easing, Camera, ITweenOption, IPunchTweenOption, IShakeTweenOption } from 'cc'; 3 | import { calcPunchData, calcShakeData } from './Util'; 4 | 5 | ////////////////////// 6 | // Transform 7 | ////////////////////// 8 | Node.prototype.qtPosition = function(to: Vec3, duration: number, opts?: ITweenOption) { 9 | return tween(this).to(duration, { position: to }, opts); 10 | } 11 | 12 | Node.prototype.qtPositionX = function(to: number, duration: number, opts?: ITweenOption) { 13 | const startPos = this.position; 14 | return tween(this).to(duration, { position: new Vec3(to, startPos.y, startPos.z) }, opts); 15 | } 16 | 17 | Node.prototype.qtPositionY = function(to: number, duration: number, opts?: ITweenOption) { 18 | const startPos = this.position; 19 | return tween(this).to(duration, { position: new Vec3(startPos.x, to, startPos.z) }, opts); 20 | } 21 | 22 | Node.prototype.qtPositionZ = function(to: number, duration: number, opts?: ITweenOption) { 23 | const startPos = this.position; 24 | return tween(this).to(duration, { position: new Vec3(startPos.x, startPos.y, to) }, opts); 25 | } 26 | 27 | Node.prototype.qtWorldPosition = function(to: Vec3, duration: number, opts?: ITweenOption) { 28 | return tween(this).to(duration, { worldPosition: to }, opts); 29 | } 30 | 31 | Node.prototype.qtWorldPositionX = function(to: number, duration: number, opts?: ITweenOption) { 32 | const startPos = this.worldPosition; 33 | return tween(this).to(duration, { worldPosition: new Vec3(to, startPos.y, startPos.z) }, opts); 34 | } 35 | 36 | Node.prototype.qtWorldPositionY = function(to: number, duration: number, opts?: ITweenOption) { 37 | const startPos = this.worldPosition; 38 | return tween(this).to(duration, { worldPosition: new Vec3(startPos.x, to, startPos.z) }, opts); 39 | } 40 | 41 | Node.prototype.qtWorldPositionZ = function(to: number, duration: number, opts?: ITweenOption) { 42 | const startPos = this.worldPosition; 43 | return tween(this).to(duration, { worldPosition: new Vec3(startPos.x, startPos.y, to) }, opts); 44 | } 45 | 46 | Node.prototype.qtRotation = function(to: Vec3, duration: number, opts?: ITweenOption) { 47 | return tween(this).to(duration, { eulerAngles: to }, opts); 48 | } 49 | 50 | Node.prototype.qtRotationQuat = function(to: Quat, duration: number, opts?: ITweenOption) { 51 | return tween(this).to(duration, { rotation: to }, opts); 52 | } 53 | 54 | Node.prototype.qtScale = function(to: Vec3|number, duration: number, opts?: ITweenOption) { 55 | let toScale = to; 56 | if (!(to instanceof Vec3)) { 57 | toScale = new Vec3(to, to, to); 58 | } 59 | 60 | return tween(this).to(duration, { scale: toScale }, opts); 61 | } 62 | 63 | Node.prototype.qtScaleX = function(to: number, duration: number, opts?: ITweenOption) { 64 | const startScale = this.scale; 65 | return tween(this).to(duration, { scale: new Vec3(to, startScale.y, startScale.z) }, opts); 66 | } 67 | 68 | Node.prototype.qtScaleY = function(to: number, duration: number, opts?: ITweenOption) { 69 | const startScale = this.scale; 70 | return tween(this).to(duration, { scale: new Vec3(startScale.x, to, startScale.z) }, opts); 71 | } 72 | 73 | Node.prototype.qtScaleZ = function(to: number, duration: number, opts?: ITweenOption) { 74 | const startScale = this.scale; 75 | return tween(this).to(duration, { scale: new Vec3(startScale.x, startScale.y, to) }, opts); 76 | } 77 | 78 | Node.prototype.qtPunchPosition = function(punch: Vec3, duration: number, opts?: IPunchTweenOption) { 79 | const vibrato = opts?.vibrato ?? 3; 80 | const elasticity = opts?.elasticity ?? 0.5; 81 | const {tos, durations} = calcPunchData(this.position.clone(), punch, duration, vibrato, elasticity); 82 | 83 | const punchTween = tween(this); 84 | tos.forEach((to, index) => { 85 | const d = durations[index]; 86 | let tweenOpts: ITweenOption|undefined; 87 | if (index === 0) { 88 | tweenOpts = { 89 | onStart: opts.onStart 90 | } 91 | } else if (index === tos.length - 1) { 92 | tweenOpts = { 93 | onComplete: opts.onComplete 94 | } 95 | } 96 | punchTween.then(tween().to(d, {position: to}, tweenOpts)); 97 | }); 98 | 99 | return punchTween.union(); 100 | } 101 | 102 | Node.prototype.qtPunchRotation = function(punch: Vec3, duration: number, opts?: IPunchTweenOption) { 103 | const vibrato = opts?.vibrato ?? 3; 104 | const elasticity = opts?.elasticity ?? 0.5; 105 | const {tos, durations} = calcPunchData(this.rotation.clone(), punch, duration, vibrato, elasticity); 106 | 107 | const punchTween = tween(this); 108 | tos.forEach((to, index) => { 109 | const d = durations[index]; 110 | let tweenOpts: ITweenOption|undefined; 111 | if (index === 0) { 112 | tweenOpts = { 113 | onStart: opts.onStart 114 | } 115 | } else if (index === tos.length - 1) { 116 | tweenOpts = { 117 | onComplete: opts.onComplete 118 | } 119 | } 120 | punchTween.then(tween().to(d, {eulerAngles: to}, tweenOpts)); 121 | }); 122 | 123 | return punchTween.union(); 124 | } 125 | 126 | Node.prototype.qtPunchScale = function(punch: Vec3, duration: number, opts?: IPunchTweenOption) { 127 | const vibrato = opts?.vibrato ?? 3; 128 | const elasticity = opts?.elasticity ?? 0.5; 129 | const {tos, durations} = calcPunchData(this.scale.clone(), punch, duration, vibrato, elasticity); 130 | 131 | const punchTween = tween(this); 132 | tos.forEach((to, index) => { 133 | const d = durations[index]; 134 | let tweenOpts: ITweenOption|undefined; 135 | if (index === 0) { 136 | tweenOpts = { 137 | onStart: opts.onStart 138 | } 139 | } else if (index === tos.length - 1) { 140 | tweenOpts = { 141 | onComplete: opts.onComplete 142 | } 143 | } 144 | punchTween.then(tween().to(d, {scale: to}, tweenOpts)); 145 | }); 146 | 147 | return punchTween.union(); 148 | } 149 | 150 | Node.prototype.qtJumpPosition = function(to: Vec3, jumpHeight: number, jumpNum: number, duration: number, opts?: ITweenOption) { 151 | const tweenPos = new Vec3(); 152 | const jumpTween = tween(this); 153 | const totalNum = jumpNum * 2; 154 | 155 | this.jumpY = 0; 156 | let startPosY = 0; 157 | const yUpTween = tween().to(duration / totalNum, { jumpY: jumpHeight }, { 158 | onStart: (target: Node) => { 159 | startPosY = target.position.y; 160 | target.jumpY = 0; 161 | }, 162 | onUpdate: (target: Node, ratio) => { 163 | tweenPos.set(target.position); 164 | tweenPos.y = startPosY + target.jumpY; 165 | target.position = tweenPos; 166 | }, 167 | onComplete: (target: Node) => { 168 | target.jumpY = 0; 169 | }, easing: 'quadOut' 170 | }).to(duration / totalNum, { jumpY: jumpHeight }, { 171 | onStart: (target: Node) => { 172 | startPosY = target.position.y; 173 | }, 174 | onUpdate: (target: Node, ratio) => { 175 | tweenPos.set(target.position); 176 | tweenPos.y = startPosY - target.jumpY; 177 | target.position = tweenPos; 178 | }, 179 | onComplete: (target: Node) => { 180 | target.jumpY = 0; 181 | }, easing: 'quadIn', 182 | }).union().repeat(jumpNum); 183 | 184 | this.jumpOffsetY = 0; 185 | let offsetY = 0; 186 | const offsetYTween = tween().to(duration, { jumpOffsetY: to.y - this.position.y }, { 187 | onStart: (target: Node) => { 188 | offsetY = to.y - target.position.y; 189 | target.jumpOffsetY = 0; 190 | }, 191 | onUpdate: (target: Node, ratio) => { 192 | const interpOffsetY = easing.quadOut(ratio) * offsetY; 193 | tweenPos.set(target.position); 194 | tweenPos.y += interpOffsetY; 195 | target.position = tweenPos; 196 | }, 197 | onComplete: (target: Node) => { 198 | target.jumpOffsetY = 0; 199 | }, easing: 'quadOut' 200 | }); 201 | 202 | this.jumpX = this.position.x; 203 | this.jumpZ = this.position.z; 204 | const xzTween = tween().to(duration, { jumpX: to.x, jumpZ: to.z }, { 205 | onStart: opts.onStart, 206 | onUpdate: (target: Node, ratio) => { 207 | tweenPos.set(target.position); 208 | tweenPos.x = target.jumpX; 209 | tweenPos.z = target.jumpZ; 210 | target.position = tweenPos; 211 | opts.onUpdate?.(); 212 | }, 213 | onComplete: (target: Node) => { 214 | // delete target.jumpX; 215 | // delete target.jumpY; 216 | // delete target.jumpZ; 217 | // delete target.jumpOffsetY; 218 | target.jumpX = target.position.x; 219 | target.jumpZ = target.position.z; 220 | opts.onComplete?.(); 221 | } 222 | }) 223 | 224 | jumpTween.parallel(yUpTween, offsetYTween, xzTween); 225 | return jumpTween; 226 | } 227 | 228 | Node.prototype.qtShakePosition = function(strength: Vec3|number, duration: number, opts?: IShakeTweenOption) { 229 | const vibrato = opts?.vibrato ?? 10; 230 | const randomness = opts?.randomness ?? 90; 231 | const fadeOut = opts?.fadeOut ?? true; 232 | let toStrength: Vec3; 233 | let vectorBased = false; 234 | if (!(strength instanceof Vec3)) { 235 | toStrength = new Vec3(strength, strength, strength); 236 | } else { 237 | toStrength = strength; 238 | vectorBased = true; 239 | } 240 | const {tos, durations} = calcShakeData(this.position.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut) 241 | const shakeTween = tween(this); 242 | tos.forEach((to, index)=> { 243 | const d = durations[index]; 244 | let tweenOpts: ITweenOption|undefined; 245 | if (index === 0) { 246 | tweenOpts = { 247 | onStart: opts.onStart 248 | } 249 | } else if (index === tos.length - 1) { 250 | tweenOpts = { 251 | onComplete: opts.onComplete 252 | } 253 | } 254 | shakeTween.then(tween().to(d, {position: to}, tweenOpts)); 255 | }); 256 | 257 | return shakeTween.union(); 258 | } 259 | 260 | Node.prototype.qtShakeRotation = function(strength: Vec3|number, duration: number, opts?: IShakeTweenOption) { 261 | const vibrato = opts?.vibrato ?? 10; 262 | const randomness = opts?.randomness ?? 90; 263 | const fadeOut = opts?.fadeOut ?? true; 264 | let toStrength: Vec3; 265 | let vectorBased = false; 266 | if (!(strength instanceof Vec3)) { 267 | toStrength = new Vec3(strength, strength, strength); 268 | } else { 269 | toStrength = strength; 270 | vectorBased = true; 271 | } 272 | const {tos, durations} = calcShakeData(this.eulerAngles.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut) 273 | const shakeTween = tween(this); 274 | tos.forEach((to, index)=> { 275 | const d = durations[index]; 276 | let tweenOpts: ITweenOption|undefined; 277 | if (index === 0) { 278 | tweenOpts = { 279 | onStart: opts.onStart 280 | } 281 | } else if (index === tos.length - 1) { 282 | tweenOpts = { 283 | onComplete: opts.onComplete 284 | } 285 | } 286 | shakeTween.then(tween().to(d, {eulerAngles: to}, tweenOpts)); 287 | }); 288 | 289 | return shakeTween.union(); 290 | } 291 | 292 | Node.prototype.qtShakeScale = function(strength: Vec3|number, duration: number, opts?: IShakeTweenOption) { 293 | const vibrato = opts?.vibrato ?? 10; 294 | const randomness = opts?.randomness ?? 90; 295 | const fadeOut = opts?.fadeOut ?? true; 296 | let toStrength: Vec3; 297 | let vectorBased = false; 298 | if (!(strength instanceof Vec3)) { 299 | toStrength = new Vec3(strength, strength, strength); 300 | } else { 301 | toStrength = strength; 302 | vectorBased = true; 303 | } 304 | const {tos, durations} = calcShakeData(this.scale.clone(), duration, toStrength, vibrato, randomness, false, vectorBased, fadeOut) 305 | const shakeTween = tween(this); 306 | tos.forEach((to, index)=> { 307 | const d = durations[index]; 308 | let tweenOpts: ITweenOption|undefined; 309 | if (index === 0) { 310 | tweenOpts = { 311 | onStart: opts.onStart 312 | } 313 | } else if (index === tos.length - 1) { 314 | tweenOpts = { 315 | onComplete: opts.onComplete 316 | } 317 | } 318 | shakeTween.then(tween().to(d, {scale: to}, tweenOpts)); 319 | }); 320 | 321 | return shakeTween.union(); 322 | } 323 | 324 | ////////////////////// 325 | // Sprite 326 | ////////////////////// 327 | // good color lerp 328 | // https://www.alanzucconi.com/2016/01/06/colour-interpolation/ 329 | Sprite.prototype.qtColor = function(to: Color, duration: number, opts?: ITweenOption) { 330 | return tween(this).to(duration, { color: to }, opts); 331 | } 332 | 333 | Sprite.prototype.qtOpacity = function(to: number, duration: number, opts?: ITweenOption) { 334 | const startColor = this.color.clone(); 335 | const tempColor = new Color(); 336 | return tween(this).to(duration, { color: new Color(startColor.r, startColor.g, startColor.b, to) }, { 337 | onStart: opts.onStart, 338 | onUpdate: (target: {_val: number}, ratio: number) => { 339 | const lerpA = startColor.a + (to - startColor.a) * ratio 340 | tempColor.set(startColor.r, startColor.g, startColor.b, lerpA); 341 | this.color = tempColor; 342 | opts.onUpdate?.(); 343 | }, 344 | onComplete: opts.onComplete 345 | }); 346 | } 347 | 348 | ////////////////////// 349 | // Camera 350 | ////////////////////// 351 | Camera.prototype.qtShakePosition = function(strength: Vec3|number, duration: number, opts?: IShakeTweenOption) { 352 | const vibrato = opts?.vibrato ?? 10; 353 | const randomness = opts?.randomness ?? 90; 354 | const fadeOut = opts?.fadeOut ?? true; 355 | let toStrength: Vec3; 356 | let vectorBased = false; 357 | if (!(strength instanceof Vec3)) { 358 | toStrength = new Vec3(strength, strength, strength); 359 | } else { 360 | toStrength = strength; 361 | vectorBased = true; 362 | } 363 | const {tos, durations} = calcShakeData(this.node.position.clone(), duration, toStrength, vibrato, randomness, true, vectorBased, fadeOut) 364 | const shakeTween = tween(this.node); 365 | tos.forEach((to, index)=> { 366 | const d = durations[index]; 367 | let tweenOpts: ITweenOption|undefined; 368 | if (index === 0) { 369 | tweenOpts = { 370 | onStart: opts.onStart 371 | } 372 | } else if (index === tos.length - 1) { 373 | tweenOpts = { 374 | onComplete: opts.onComplete 375 | } 376 | } 377 | shakeTween.then(tween().to(d, {position: to}, tweenOpts)); 378 | }); 379 | 380 | return shakeTween.union(); 381 | } -------------------------------------------------------------------------------- /assets/QuickTween/QuickTween.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.22", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "205317ea-6dc0-4c75-800e-a998dd16d963", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /assets/QuickTween/Util.ts: -------------------------------------------------------------------------------- 1 | import { KeyCode, math, Quat, Vec3 } from "cc"; 2 | 3 | export function clampLength(vec: Vec3, maxLength: number) { 4 | if (vec.lengthSqr() > maxLength * maxLength) { 5 | const clampVec = new Vec3(); 6 | Vec3.normalize(clampVec, vec); 7 | clampVec.multiplyScalar(maxLength); 8 | return clampVec; 9 | } 10 | 11 | return vec; 12 | } 13 | 14 | export function vec3FromAngle(degree: number, length: number) { 15 | const radian = math.toRadian(degree); 16 | return new Vec3(length * Math.cos(radian), length * Math.sin(radian), 0); 17 | } 18 | 19 | export function calcPunchData(start: Vec3, direction: Vec3, duration: number, vibrato: number, elasticity: number) { 20 | math.clamp01(elasticity); 21 | let strength = direction.length(); 22 | let toIterations = Math.round(vibrato * duration); 23 | if (toIterations < 2) { 24 | toIterations = 2; 25 | } 26 | 27 | const deltaStrength = strength / toIterations; 28 | 29 | let durations = []; 30 | let sum = 0; 31 | for (let i = 0; i < toIterations; i++) { 32 | const iterationPercent = (i + 1) / toIterations; 33 | const deltaDuration = duration * iterationPercent; 34 | sum += deltaDuration; 35 | durations[i] = deltaDuration; 36 | } 37 | 38 | const durationMultiplier = duration / sum; 39 | durations = durations.map((d) => d * durationMultiplier ); 40 | 41 | // create to vec3 array 42 | const tos: Vec3[] = []; 43 | for(let i = 0; i < toIterations; i++) { 44 | if (i < toIterations - 1) { 45 | if (i === 0) { 46 | tos[i] = Vec3.add(new Vec3(), start, direction); 47 | } else if (i % 2 !== 0) { 48 | const deltaVec = clampLength(direction, strength * elasticity); 49 | deltaVec.negative(); 50 | tos[i] = deltaVec.add(start); 51 | } else { 52 | const deltaVec = clampLength(direction, strength); 53 | tos[i] = deltaVec.add(start); 54 | } 55 | } else { 56 | tos[i] = start; 57 | } 58 | 59 | strength -= deltaStrength; 60 | } 61 | 62 | return { 63 | tos, 64 | durations 65 | } 66 | } 67 | 68 | export function calcShakeData(start: Vec3, duration: number, strength: Vec3, vibrato: number, randomness: number, ignoreZAxis: boolean, vectorBased: boolean, 69 | fadeOut: boolean) { 70 | KeyCode 71 | let shakeLength = vectorBased ? strength.length() : strength.x; 72 | let toIterations = Math.floor(vibrato * duration); 73 | if (toIterations < 2) { 74 | toIterations = 2; 75 | } 76 | const deltaShakeLen = shakeLength / toIterations; 77 | let durations = []; 78 | let sum = 0; 79 | for (let i = 0; i < toIterations; i++) { 80 | const iterationPercent = (i + 1) / toIterations; 81 | const deltaDuration = fadeOut ? duration * iterationPercent : duration / toIterations; 82 | sum += deltaDuration; 83 | durations[i] = deltaDuration; 84 | } 85 | 86 | const durationMultiplier = duration / sum; 87 | durations = durations.map((d) => d * durationMultiplier ); 88 | 89 | let angle = math.randomRange(0, 360); 90 | const tos: Vec3[] =[]; 91 | 92 | for (let i = 0; i < toIterations; i++) { 93 | if (i < toIterations - 1) { 94 | let randQuat = new Quat(); 95 | if (i > 0) { 96 | angle = angle - 180 + math.randomRange(-randomness, randomness); 97 | } 98 | // switch(randomnessMode) { 99 | // case ShakeRandomnessMode.Harmonic: 100 | // if (i > 0) { 101 | // angle = angle - 180 + math.randomRange(0, randomness); 102 | // } 103 | // if (vectorBased || !ignoreZAxis) { 104 | // Quat.fromAxisAngle(randQuat, Vec3.UP, math.randomRange(0, randomness)); 105 | // } 106 | // break; 107 | // default: 108 | // if (i > 0) { 109 | // angle = angle - 180 + math.randomRange(-randomness, randomness); 110 | // } 111 | // if (vectorBased || !ignoreZAxis) { 112 | // Quat.fromAxisAngle(randQuat, Vec3.UP, math.randomRange(-randomness, randomness)); 113 | // } 114 | // break; 115 | // } 116 | 117 | if (vectorBased) { 118 | let to = vec3FromAngle(angle, shakeLength); 119 | Vec3.transformQuat(to, to, randQuat); 120 | to.x = clampLength(to, strength.x).x; 121 | to.y = clampLength(to, strength.y).y; 122 | to.z = clampLength(to, strength.z).z; 123 | to.normalize().multiplyScalar(shakeLength); 124 | tos[i] = to.add(start); 125 | if (fadeOut) { 126 | shakeLength -= deltaShakeLen; 127 | } 128 | strength = clampLength(strength, shakeLength); 129 | } else { 130 | if (ignoreZAxis) { 131 | tos[i] = vec3FromAngle(angle, shakeLength).add(start); 132 | } else { 133 | Quat.fromAxisAngle(randQuat, Vec3.UP, math.randomRange(-randomness, randomness)); 134 | let to = vec3FromAngle(angle, shakeLength); 135 | Vec3.transformQuat(to, to, randQuat); 136 | tos[i] = to.add(start); 137 | } 138 | 139 | if (fadeOut) { 140 | shakeLength -= deltaShakeLen; 141 | } 142 | } 143 | } else { 144 | tos[i] = start; 145 | } 146 | } 147 | 148 | return { 149 | tos, 150 | durations 151 | } 152 | } -------------------------------------------------------------------------------- /assets/QuickTween/Util.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.22", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "c427c54a-84cb-43e9-b420-9e3c6c6a3fa0", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /assets/QuickTween/quick-tween.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'cc' { 2 | 3 | interface IPunchTweenOption extends ITweenOption { 4 | // How much the punch will vibrate 5 | vibrato?: number, 6 | // Represents how much (0 to 1) the vector will go beyond the starting position 7 | // when bouncing backwards. 1 creates a full oscillation between the punch direction and the 8 | // opposite direction, while 0 oscillates only between the punch and the start scale. 9 | elasticity?: number 10 | } 11 | 12 | interface IShakeTweenOption extends ITweenOption { 13 | vibrato?: number //每秒振动次数 14 | randomness?: number // 随机角度值 15 | fadeOut?: boolean // 是否淡出 16 | } 17 | 18 | interface Node { 19 | /** 20 | * @zh 21 | * 移动目标的坐标到指定位置 22 | * @en 23 | * Moves the target's position to the given value 24 | * @param to dest position 25 | * @param duration time in seconds 26 | * @param {ITweenOption} opts options for tween 27 | * @param {Function} opts.onStart start callback 28 | */ 29 | qtPosition(to: Vec3, duration: number, opts?: ITweenOption): Tween; 30 | /** 31 | * @zh 32 | * 移动目标的坐标到指定位置, 只移动X坐标 33 | * @en 34 | * Moves the target's position to the given value, tweening only the X axis. 35 | * @param to dest position 36 | * @param duration time in seconds 37 | * @param opts options for tween 38 | */ 39 | qtPositionX(to: number, duration: number, opts?: ITweenOption): Tween; 40 | /** 41 | * @zh 42 | * 移动目标的坐标到指定位置, 只移动Y坐标 43 | * @en 44 | * Moves the target's position to the given value, tweening only the Y axis. 45 | * @param to dest position 46 | * @param duration time in seconds 47 | * @param opts options for tween 48 | */ 49 | qtPositionY(to: number, duration: number, opts?: ITweenOption): Tween; 50 | /** 51 | * @zh 52 | * 移动目标的坐标到指定位置, 只移动Z坐标 53 | * @en 54 | * Moves the target's position to the given value, tweening only the Z axis. 55 | * @param to dest position 56 | * @param duration time in seconds 57 | * @param opts options for tween 58 | */ 59 | qtPositionZ(to: number, duration: number, opts?: ITweenOption): Tween; 60 | /** 61 | * @zh 62 | * 移动目标的世界坐标到指定位置 63 | * @en 64 | * Moves the target's worldPosition to the given value 65 | * @param to dest position 66 | * @param duration time in seconds 67 | * @param opts options for tween 68 | */ 69 | qtWorldPosition(to: Vec3, duration: number, opts?: ITweenOption): Tween; 70 | /** 71 | * @zh 72 | * 移动目标的世界坐标到指定位置, 只移动X坐标 73 | * @en 74 | * Moves the target's worldPosition to the given value, tweening only the X axis. 75 | * @param to dest position 76 | * @param duration time in seconds 77 | * @param opts options for tween 78 | */ 79 | qtWorldPositionX(to: number, duration: number, opts?: ITweenOption): Tween; 80 | /** 81 | * @zh 82 | * 移动目标的世界坐标到指定位置, 只移动Y坐标 83 | * @en 84 | * Moves the target's worldPosition to the given value, tweening only the Y axis. 85 | * @param to dest position 86 | * @param duration time in seconds 87 | * @param opts options for tween 88 | */ 89 | qtWorldPositionY(to: number, duration: number, opts?: ITweenOption): Tween; 90 | /** 91 | * @zh 92 | * 移动目标的世界坐标到指定位置, 只移动Z坐标 93 | * @en 94 | * Moves the target's worldPosition to the given value, tweening only the Z axis. 95 | * @param to dest position 96 | * @param duration time in seconds 97 | * @param opts options for tween 98 | */ 99 | qtWorldPositionZ(to: number, duration: number, opts?: ITweenOption): Tween; 100 | /** 101 | * @zh 102 | * 旋转目标到指定值 103 | * @en 104 | * Rotates the target to ghe given value 105 | * @param to dest rotation in eulerAngle 106 | * @param duration time in seconds 107 | * @param opts options for tween 108 | */ 109 | qtRotation(to: Vec3, duration: number, opts?: ITweenOption): Tween; 110 | /** 111 | * @zh 112 | * 旋转目标到指定值 113 | * @en 114 | * Rotates the target to ghe given value 115 | * @param to dest rotation in quaternion 116 | * @param duration time in seconds 117 | * @param opts options for tween 118 | */ 119 | qtRotationQuat(to: Quat, duration: number, opts?: ITweenOption): Tween; 120 | /** 121 | * @zh 122 | * 缩放目标到指定值 123 | * @en 124 | * Scales the target to ghe given value 125 | * @param to dest scale value 126 | * @param duration time in seconds 127 | * @param opts options for tween 128 | */ 129 | qtScale(to: Vec3|number, duration: number, opts?: ITweenOption): Tween; 130 | /** 131 | * @zh 132 | * 缩放目标到指定值,只影响X轴 133 | * @en 134 | * Scales the target to ghe given value, tweening only X axis 135 | * @param to dest scale value 136 | * @param duration time in seconds 137 | * @param opts options for tween 138 | */ 139 | qtScaleX(to: number, duration: number, opts?: ITweenOption): Tween; 140 | /** 141 | * @zh 142 | * 缩放目标到指定值,只影响Y轴 143 | * @en 144 | * Scales the target to ghe given value, tweening only Y axis 145 | * @param to dest scale value 146 | * @param duration time in seconds 147 | * @param opts options for tween 148 | */ 149 | qtScaleY(to: number, duration: number, opts?: ITweenOption): Tween; 150 | /** 151 | * @zh 152 | * 缩放目标到指定值,只影响Z轴 153 | * @en 154 | * Scales the target to ghe given value, tweening only Z axis 155 | * @param to dest scale value 156 | * @param duration time in seconds 157 | * @param opts options for tween 158 | */ 159 | qtScaleZ(to: number, duration: number, opts?: ITweenOption): Tween; 160 | 161 | /** 162 | * @zh 163 | * 击打目标位置到指定方向,然后回到初始值 164 | * @en 165 | * Punches a position towards the given direction and then 166 | * back to the starting one as if it was connected to the starting position 167 | * via an elastic. 168 | * @param punch The direction and strength of the punch, (added to the node's current position) 169 | * @param duration Time in seconds 170 | * @param {IPunchTweenOption} opts punch tween options 171 | * @param {number} opts.vibrato How much the punch will vibrate 172 | * @param {number} opts.elasticity Represents how much (0 to 1) the vector will go beyond the starting position 173 | * when bouncing backwards. 1 creates a full oscillation between the punch direction and the 174 | * opposite direction, while 0 oscillates only between the punch and the start position. 175 | */ 176 | qtPunchPosition(punch: Vec3, duration: number, opts?: IPunchTweenOption): Tween; 177 | 178 | /** 179 | * @zh 180 | * 击打目标旋转方向到指定值,然后回到初始值 181 | * @en 182 | * Punches a rotation to the given value and then back to the starting one as if it was connected 183 | * to the starting rotation via an elastic. 184 | * @param punch The strength of punch, (added to the node's current rotation) 185 | * @param duration Time in seconds 186 | * @param {IPunchTweenOption} opts punch tween options 187 | * @param {number} opts.vibrato How much the punch will vibrate 188 | * @param {number} opts.elasticity Represents how much (0 to 1) the vector will go beyond the starting position 189 | * when bouncing backwards. 1 creates a full oscillation between the punch direction and the 190 | * opposite direction, while 0 oscillates only between the punch and the start rotation. 191 | */ 192 | qtPunchRotation(punch: Vec3, duration: number, opts?: IPunchTweenOption): Tween; 193 | 194 | /** 195 | * @zh 196 | * 击打目标缩放到指定值,然后回到初始值 197 | * @en 198 | * Punches a scale to the given value and then back to the starting one as if it was connected 199 | * to the starting scale via an elastic. 200 | * @param punch The strength of punch, (added to the node's current scale) 201 | * @param duration Time in seconds 202 | * @param {IPunchTweenOption} opts punch tween options 203 | * @param {number} opts.vibrato How much the punch will vibrate 204 | * @param {number} opts.elasticity Represents how much (0 to 1) the vector will go beyond the starting position 205 | * when bouncing backwards. 1 creates a full oscillation between the punch direction and the 206 | * opposite direction, while 0 oscillates only between the punch and the start scale. 207 | */ 208 | qtPunchScale(punch: Vec3, duration: number, opts?: IPunchTweenOption): Tween; 209 | 210 | jumpX?: number; 211 |         jumpY?: number; 212 |         jumpZ?: number; 213 |         jumpOffsetY?: number; 214 | /** 215 | * @zh 216 | * 缓动目标的坐标到指定值,在移动过程中同时附加一个Y坐标的高度值来模拟跳跃动作 217 | * @en 218 | * Tweens the target's position to the given value, while also applying a jump effect along the Y axis. 219 | * @param to 目标坐标值 220 | * @param jumpHeight 跳跃高度 221 | * @param jumpNum 跳跃次数 222 | * @param duration 时间 223 | * @param opts tween options 224 | */ 225 | qtJumpPosition(to: Vec3, jumpHeight: number, jumpNum: number, duration: number, opts?: ITweenOption): Tween; 226 | 227 | /** 228 | * @zh 229 | * 使目标的位置在设定的参数下抖动 230 | * @en 231 | * Shakes the target's position with the given values 232 | * @param strength 强度 233 | * @param duration 时间 234 | * @param {IShakeTweenOption} opts shake tween options 235 | * @param {number} opts.vibrato 每秒振动次数 236 | * @param {number} opts.randomness 随机角度值 237 | * @param {boolean} opts.fadeOut 是否淡出 238 | */ 239 | qtShakePosition(strength: Vec3|number, duration: number, opts?: IShakeTweenOption): Tween; 240 | 241 | /** 242 | * @zh 243 | * 使目标的旋转在设定的参数下抖动 244 | * @en 245 | * Shakes the target's rotation with the given values 246 | * @param strength 强度 247 | * @param duration 时间 248 | * @param {IShakeTweenOption} opts shake tween options 249 | * @param {number} opts.vibrato 每秒振动次数 250 | * @param {number} opts.randomness 随机角度值 251 | * @param {boolean} opts.fadeOut 是否淡出 252 | */ 253 | qtShakeRotation(strength: Vec3|number, duration: number, opts?: IShakeTweenOption): Tween; 254 | 255 | /** 256 | * @zh 257 | * 使目标的缩放在设定的参数下抖动 258 | * @en 259 | * Shakes the target's scale with the given values 260 | * @param strength 强度 261 | * @param duration 时间 262 | * @param {IShakeTweenOption} opts shake tween options 263 | * @param {number} opts.vibrato 每秒振动次数 264 | * @param {number} opts.randomness 随机角度值 265 | * @param {boolean} opts.fadeOut 是否淡出 266 | */ 267 | qtShakeScale(strength: Vec3|number, duration: number, opts?: IShakeTweenOption): Tween; 268 | } 269 | 270 | interface Sprite { 271 | qtColor(to: Color, duration: number, opts?: ITweenOption): Tween; 272 | qtOpacity(to: number, duration: number, opts?: ITweenOption): Tween; 273 | } 274 | 275 | interface Camera { 276 | /** 277 | * @zh 278 | * 使目标的位置在设定的参数下抖动 279 | * @en 280 | * Shakes the target's position with the given values 281 | * @param strength 强度 282 | * @param duration 时间 283 | * @param {IShakeTweenOption} opts shake tween options 284 | * @param {number} opts.vibrato 每秒振动次数 285 | * @param {number} opts.randomness 随机角度值 286 | * @param {boolean} opts.fadeOut 是否淡出 287 | */ 288 | qtShakePosition(strength: Vec3|number, duration: number, opts?: IShakeTweenOption): Tween; 289 | } 290 | } -------------------------------------------------------------------------------- /assets/QuickTween/quick-tween.d.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.22", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "65f4e608-0b85-444e-9fe3-968f4ce6d181", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "8f5f0cea-11a8-4d1e-9b8c-e462994a9746", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /assets/Scenes/TestJump.scene: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__type__": "cc.SceneAsset", 4 | "_name": "", 5 | "_objFlags": 0, 6 | "_native": "", 7 | "scene": { 8 | "__id__": 1 9 | } 10 | }, 11 | { 12 | "__type__": "cc.Scene", 13 | "_name": "TestJump", 14 | "_objFlags": 0, 15 | "_parent": null, 16 | "_children": [ 17 | { 18 | "__id__": 2 19 | }, 20 | { 21 | "__id__": 5 22 | }, 23 | { 24 | "__id__": 7 25 | }, 26 | { 27 | "__id__": 9 28 | }, 29 | { 30 | "__id__": 12 31 | } 32 | ], 33 | "_active": true, 34 | "_components": [], 35 | "_prefab": null, 36 | "autoReleaseAssets": false, 37 | "_globals": { 38 | "__id__": 26 39 | }, 40 | "_id": "18134532-7de1-40a6-beee-e26fe8e7bb26" 41 | }, 42 | { 43 | "__type__": "cc.Node", 44 | "_name": "Main Light", 45 | "_objFlags": 0, 46 | "_parent": { 47 | "__id__": 1 48 | }, 49 | "_children": [], 50 | "_active": true, 51 | "_components": [ 52 | { 53 | "__id__": 3 54 | } 55 | ], 56 | "_prefab": null, 57 | "_lpos": { 58 | "__type__": "cc.Vec3", 59 | "x": 0, 60 | "y": 0, 61 | "z": 0 62 | }, 63 | "_lrot": { 64 | "__type__": "cc.Quat", 65 | "x": -0.24999999999999997, 66 | "y": -0.24999999999999997, 67 | "z": -0.06698729810778066, 68 | "w": 0.9330127018922194 69 | }, 70 | "_lscale": { 71 | "__type__": "cc.Vec3", 72 | "x": 1, 73 | "y": 1, 74 | "z": 1 75 | }, 76 | "_layer": 1073741824, 77 | "_euler": { 78 | "__type__": "cc.Vec3", 79 | "x": -30, 80 | "y": -30, 81 | "z": 0 82 | }, 83 | "_id": "c0y6F5f+pAvI805TdmxIjx" 84 | }, 85 | { 86 | "__type__": "cc.DirectionalLight", 87 | "_name": "", 88 | "_objFlags": 0, 89 | "node": { 90 | "__id__": 2 91 | }, 92 | "_enabled": true, 93 | "__prefab": null, 94 | "_color": { 95 | "__type__": "cc.Color", 96 | "r": 255, 97 | "g": 255, 98 | "b": 255, 99 | "a": 255 100 | }, 101 | "_useColorTemperature": false, 102 | "_colorTemperature": 6550, 103 | "_staticSettings": { 104 | "__id__": 4 105 | }, 106 | "_illuminance": 65000, 107 | "_id": "597uMYCbhEtJQc0ffJlcgA" 108 | }, 109 | { 110 | "__type__": "cc.StaticLightSettings", 111 | "_baked": false, 112 | "_editorOnly": false, 113 | "_bakeable": false, 114 | "_castShadow": false 115 | }, 116 | { 117 | "__type__": "cc.Node", 118 | "_name": "Main Camera", 119 | "_objFlags": 0, 120 | "_parent": { 121 | "__id__": 1 122 | }, 123 | "_children": [], 124 | "_active": true, 125 | "_components": [ 126 | { 127 | "__id__": 6 128 | } 129 | ], 130 | "_prefab": null, 131 | "_lpos": { 132 | "__type__": "cc.Vec3", 133 | "x": 0, 134 | "y": 2, 135 | "z": 8 136 | }, 137 | "_lrot": { 138 | "__type__": "cc.Quat", 139 | "x": -0.08715574274765817, 140 | "y": 1.5119111301055797e-19, 141 | "z": -1.7281223294233787e-18, 142 | "w": 0.9961946980917455 143 | }, 144 | "_lscale": { 145 | "__type__": "cc.Vec3", 146 | "x": 1, 147 | "y": 1, 148 | "z": 1 149 | }, 150 | "_layer": 1073741824, 151 | "_euler": { 152 | "__type__": "cc.Vec3", 153 | "x": -10, 154 | "y": 0, 155 | "z": -1.987846675914698e-16 156 | }, 157 | "_id": "c9DMICJLFO5IeO07EPon7U" 158 | }, 159 | { 160 | "__type__": "cc.Camera", 161 | "_name": "", 162 | "_objFlags": 0, 163 | "node": { 164 | "__id__": 5 165 | }, 166 | "_enabled": true, 167 | "__prefab": null, 168 | "_projection": 1, 169 | "_priority": 0, 170 | "_fov": 45, 171 | "_fovAxis": 0, 172 | "_orthoHeight": 10, 173 | "_near": 1, 174 | "_far": 1000, 175 | "_color": { 176 | "__type__": "cc.Color", 177 | "r": 51, 178 | "g": 51, 179 | "b": 51, 180 | "a": 255 181 | }, 182 | "_depth": 1, 183 | "_stencil": 0, 184 | "_clearFlags": 7, 185 | "_rect": { 186 | "__type__": "cc.Rect", 187 | "x": 0, 188 | "y": 0, 189 | "width": 1, 190 | "height": 1 191 | }, 192 | "_aperture": 19, 193 | "_shutter": 7, 194 | "_iso": 0, 195 | "_screenScale": 1, 196 | "_visibility": 1822425087, 197 | "_targetTexture": null, 198 | "_id": "7dWQTpwS5LrIHnc1zAPUtf" 199 | }, 200 | { 201 | "__type__": "cc.Node", 202 | "_name": "TestJump", 203 | "_objFlags": 0, 204 | "_parent": { 205 | "__id__": 1 206 | }, 207 | "_children": [], 208 | "_active": true, 209 | "_components": [ 210 | { 211 | "__id__": 8 212 | } 213 | ], 214 | "_prefab": null, 215 | "_lpos": { 216 | "__type__": "cc.Vec3", 217 | "x": 0, 218 | "y": 0, 219 | "z": 0 220 | }, 221 | "_lrot": { 222 | "__type__": "cc.Quat", 223 | "x": 0, 224 | "y": 0, 225 | "z": 0, 226 | "w": 1 227 | }, 228 | "_lscale": { 229 | "__type__": "cc.Vec3", 230 | "x": 1, 231 | "y": 1, 232 | "z": 1 233 | }, 234 | "_layer": 1073741824, 235 | "_euler": { 236 | "__type__": "cc.Vec3", 237 | "x": 0, 238 | "y": 0, 239 | "z": 0 240 | }, 241 | "_id": "eeg0JYrZVIIIXqUsDcpKmN" 242 | }, 243 | { 244 | "__type__": "5c687YB9CJA2J2+/JYuJNuq", 245 | "_name": "", 246 | "_objFlags": 0, 247 | "node": { 248 | "__id__": 7 249 | }, 250 | "_enabled": true, 251 | "__prefab": null, 252 | "testCube": { 253 | "__id__": 9 254 | }, 255 | "testCamera": { 256 | "__id__": 6 257 | }, 258 | "_id": "b4xNR+WjFIp7C8mCJqbjM2" 259 | }, 260 | { 261 | "__type__": "cc.Node", 262 | "_name": "Cube", 263 | "_objFlags": 0, 264 | "_parent": { 265 | "__id__": 1 266 | }, 267 | "_children": [], 268 | "_active": true, 269 | "_components": [ 270 | { 271 | "__id__": 10 272 | } 273 | ], 274 | "_prefab": null, 275 | "_lpos": { 276 | "__type__": "cc.Vec3", 277 | "x": 0, 278 | "y": 0, 279 | "z": 0 280 | }, 281 | "_lrot": { 282 | "__type__": "cc.Quat", 283 | "x": 0, 284 | "y": 0, 285 | "z": 0, 286 | "w": 1 287 | }, 288 | "_lscale": { 289 | "__type__": "cc.Vec3", 290 | "x": 1, 291 | "y": 1, 292 | "z": 1 293 | }, 294 | "_layer": 1073741824, 295 | "_euler": { 296 | "__type__": "cc.Vec3", 297 | "x": 0, 298 | "y": 0, 299 | "z": 0 300 | }, 301 | "_id": "08SHh+rqNAdYVE0772jwGX" 302 | }, 303 | { 304 | "__type__": "cc.MeshRenderer", 305 | "_name": "Cube", 306 | "_objFlags": 0, 307 | "node": { 308 | "__id__": 9 309 | }, 310 | "_enabled": true, 311 | "__prefab": null, 312 | "_materials": [ 313 | { 314 | "__uuid__": "d3c7820c-2a98-4429-8bc7-b8453bc9ac41", 315 | "__expectedType__": "cc.Material" 316 | } 317 | ], 318 | "_visFlags": 0, 319 | "lightmapSettings": { 320 | "__id__": 11 321 | }, 322 | "_mesh": { 323 | "__uuid__": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", 324 | "__expectedType__": "cc.Mesh" 325 | }, 326 | "_shadowCastingMode": 0, 327 | "_shadowReceivingMode": 1, 328 | "_enableMorph": true, 329 | "_id": "45QznhDqhG5abYlPvkqdC6" 330 | }, 331 | { 332 | "__type__": "cc.ModelLightmapSettings", 333 | "texture": null, 334 | "uvParam": { 335 | "__type__": "cc.Vec4", 336 | "x": 0, 337 | "y": 0, 338 | "z": 0, 339 | "w": 0 340 | }, 341 | "_bakeable": false, 342 | "_castShadow": false, 343 | "_receiveShadow": false, 344 | "_recieveShadow": false, 345 | "_lightmapSize": 64 346 | }, 347 | { 348 | "__type__": "cc.Node", 349 | "_name": "Canvas", 350 | "_objFlags": 0, 351 | "_parent": { 352 | "__id__": 1 353 | }, 354 | "_children": [ 355 | { 356 | "__id__": 13 357 | }, 358 | { 359 | "__id__": 15 360 | } 361 | ], 362 | "_active": true, 363 | "_components": [ 364 | { 365 | "__id__": 23 366 | }, 367 | { 368 | "__id__": 24 369 | }, 370 | { 371 | "__id__": 25 372 | } 373 | ], 374 | "_prefab": null, 375 | "_lpos": { 376 | "__type__": "cc.Vec3", 377 | "x": 480, 378 | "y": 320, 379 | "z": 0 380 | }, 381 | "_lrot": { 382 | "__type__": "cc.Quat", 383 | "x": 0, 384 | "y": 0, 385 | "z": 0, 386 | "w": 1 387 | }, 388 | "_lscale": { 389 | "__type__": "cc.Vec3", 390 | "x": 1, 391 | "y": 1, 392 | "z": 1 393 | }, 394 | "_layer": 33554432, 395 | "_euler": { 396 | "__type__": "cc.Vec3", 397 | "x": 0, 398 | "y": 0, 399 | "z": 0 400 | }, 401 | "_id": "bf1KER68NIh5p8k26XXSkx" 402 | }, 403 | { 404 | "__type__": "cc.Node", 405 | "_name": "Camera", 406 | "_objFlags": 0, 407 | "_parent": { 408 | "__id__": 12 409 | }, 410 | "_children": [], 411 | "_active": true, 412 | "_components": [ 413 | { 414 | "__id__": 14 415 | } 416 | ], 417 | "_prefab": null, 418 | "_lpos": { 419 | "__type__": "cc.Vec3", 420 | "x": 0, 421 | "y": 0, 422 | "z": 1000 423 | }, 424 | "_lrot": { 425 | "__type__": "cc.Quat", 426 | "x": 0, 427 | "y": 0, 428 | "z": 0, 429 | "w": 1 430 | }, 431 | "_lscale": { 432 | "__type__": "cc.Vec3", 433 | "x": 1, 434 | "y": 1, 435 | "z": 1 436 | }, 437 | "_layer": 1073741824, 438 | "_euler": { 439 | "__type__": "cc.Vec3", 440 | "x": 0, 441 | "y": 0, 442 | "z": 0 443 | }, 444 | "_id": "d9tJTJoElMCYtdU9za0hg0" 445 | }, 446 | { 447 | "__type__": "cc.Camera", 448 | "_name": "", 449 | "_objFlags": 0, 450 | "node": { 451 | "__id__": 13 452 | }, 453 | "_enabled": true, 454 | "__prefab": null, 455 | "_projection": 0, 456 | "_priority": 1073741824, 457 | "_fov": 45, 458 | "_fovAxis": 0, 459 | "_orthoHeight": 320, 460 | "_near": 1, 461 | "_far": 2000, 462 | "_color": { 463 | "__type__": "cc.Color", 464 | "r": 0, 465 | "g": 0, 466 | "b": 0, 467 | "a": 255 468 | }, 469 | "_depth": 1, 470 | "_stencil": 0, 471 | "_clearFlags": 6, 472 | "_rect": { 473 | "__type__": "cc.Rect", 474 | "x": 0, 475 | "y": 0, 476 | "width": 1, 477 | "height": 1 478 | }, 479 | "_aperture": 19, 480 | "_shutter": 7, 481 | "_iso": 0, 482 | "_screenScale": 1, 483 | "_visibility": 41943040, 484 | "_targetTexture": null, 485 | "_id": "3bOo/BWr9ATLpum8aGJv5/" 486 | }, 487 | { 488 | "__type__": "cc.Node", 489 | "_name": "Button", 490 | "_objFlags": 0, 491 | "_parent": { 492 | "__id__": 12 493 | }, 494 | "_children": [ 495 | { 496 | "__id__": 16 497 | } 498 | ], 499 | "_active": true, 500 | "_components": [ 501 | { 502 | "__id__": 19 503 | }, 504 | { 505 | "__id__": 20 506 | }, 507 | { 508 | "__id__": 21 509 | } 510 | ], 511 | "_prefab": null, 512 | "_lpos": { 513 | "__type__": "cc.Vec3", 514 | "x": 0, 515 | "y": -287.09, 516 | "z": 0 517 | }, 518 | "_lrot": { 519 | "__type__": "cc.Quat", 520 | "x": 0, 521 | "y": 0, 522 | "z": 0, 523 | "w": 1 524 | }, 525 | "_lscale": { 526 | "__type__": "cc.Vec3", 527 | "x": 1, 528 | "y": 1, 529 | "z": 1 530 | }, 531 | "_layer": 33554432, 532 | "_euler": { 533 | "__type__": "cc.Vec3", 534 | "x": 0, 535 | "y": 0, 536 | "z": 0 537 | }, 538 | "_id": "98tih5s6tKvIRvLgz4r/5+" 539 | }, 540 | { 541 | "__type__": "cc.Node", 542 | "_name": "Label", 543 | "_objFlags": 512, 544 | "_parent": { 545 | "__id__": 15 546 | }, 547 | "_children": [], 548 | "_active": true, 549 | "_components": [ 550 | { 551 | "__id__": 17 552 | }, 553 | { 554 | "__id__": 18 555 | } 556 | ], 557 | "_prefab": null, 558 | "_lpos": { 559 | "__type__": "cc.Vec3", 560 | "x": 0, 561 | "y": 0, 562 | "z": 0 563 | }, 564 | "_lrot": { 565 | "__type__": "cc.Quat", 566 | "x": 0, 567 | "y": 0, 568 | "z": 0, 569 | "w": 1 570 | }, 571 | "_lscale": { 572 | "__type__": "cc.Vec3", 573 | "x": 1, 574 | "y": 1, 575 | "z": 1 576 | }, 577 | "_layer": 33554432, 578 | "_euler": { 579 | "__type__": "cc.Vec3", 580 | "x": 0, 581 | "y": 0, 582 | "z": 0 583 | }, 584 | "_id": "98nqYYu1VF+75a7B9Fplaw" 585 | }, 586 | { 587 | "__type__": "cc.UITransform", 588 | "_name": "", 589 | "_objFlags": 0, 590 | "node": { 591 | "__id__": 16 592 | }, 593 | "_enabled": true, 594 | "__prefab": null, 595 | "_contentSize": { 596 | "__type__": "cc.Size", 597 | "width": 100, 598 | "height": 40 599 | }, 600 | "_anchorPoint": { 601 | "__type__": "cc.Vec2", 602 | "x": 0.5, 603 | "y": 0.5 604 | }, 605 | "_id": "96DcnbUutNgqnl82O4Pi4M" 606 | }, 607 | { 608 | "__type__": "cc.Label", 609 | "_name": "", 610 | "_objFlags": 0, 611 | "node": { 612 | "__id__": 16 613 | }, 614 | "_enabled": true, 615 | "__prefab": null, 616 | "_visFlags": 0, 617 | "_customMaterial": null, 618 | "_srcBlendFactor": 2, 619 | "_dstBlendFactor": 4, 620 | "_color": { 621 | "__type__": "cc.Color", 622 | "r": 0, 623 | "g": 0, 624 | "b": 0, 625 | "a": 255 626 | }, 627 | "_string": "jump", 628 | "_horizontalAlign": 1, 629 | "_verticalAlign": 1, 630 | "_actualFontSize": 20, 631 | "_fontSize": 20, 632 | "_fontFamily": "Arial", 633 | "_lineHeight": 40, 634 | "_overflow": 1, 635 | "_enableWrapText": false, 636 | "_font": null, 637 | "_isSystemFontUsed": true, 638 | "_isItalic": false, 639 | "_isBold": false, 640 | "_isUnderline": false, 641 | "_underlineHeight": 2, 642 | "_cacheMode": 0, 643 | "_id": "e22wCmnvFNZJUCoYyye7Hf" 644 | }, 645 | { 646 | "__type__": "cc.UITransform", 647 | "_name": "", 648 | "_objFlags": 0, 649 | "node": { 650 | "__id__": 15 651 | }, 652 | "_enabled": true, 653 | "__prefab": null, 654 | "_contentSize": { 655 | "__type__": "cc.Size", 656 | "width": 100, 657 | "height": 40 658 | }, 659 | "_anchorPoint": { 660 | "__type__": "cc.Vec2", 661 | "x": 0.5, 662 | "y": 0.5 663 | }, 664 | "_id": "e8wLMjb9hAdJbmVE3U4Bbh" 665 | }, 666 | { 667 | "__type__": "cc.Sprite", 668 | "_name": "", 669 | "_objFlags": 0, 670 | "node": { 671 | "__id__": 15 672 | }, 673 | "_enabled": true, 674 | "__prefab": null, 675 | "_visFlags": 0, 676 | "_customMaterial": null, 677 | "_srcBlendFactor": 2, 678 | "_dstBlendFactor": 4, 679 | "_color": { 680 | "__type__": "cc.Color", 681 | "r": 255, 682 | "g": 255, 683 | "b": 255, 684 | "a": 255 685 | }, 686 | "_spriteFrame": { 687 | "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", 688 | "__expectedType__": "cc.SpriteFrame" 689 | }, 690 | "_type": 1, 691 | "_fillType": 0, 692 | "_sizeMode": 0, 693 | "_fillCenter": { 694 | "__type__": "cc.Vec2", 695 | "x": 0, 696 | "y": 0 697 | }, 698 | "_fillStart": 0, 699 | "_fillRange": 0, 700 | "_isTrimmedMode": true, 701 | "_useGrayscale": false, 702 | "_atlas": null, 703 | "_id": "28I5hULDVLx6+OtKhXAgXa" 704 | }, 705 | { 706 | "__type__": "cc.Button", 707 | "_name": "", 708 | "_objFlags": 0, 709 | "node": { 710 | "__id__": 15 711 | }, 712 | "_enabled": true, 713 | "__prefab": null, 714 | "clickEvents": [ 715 | { 716 | "__id__": 22 717 | } 718 | ], 719 | "_interactable": true, 720 | "_transition": 2, 721 | "_normalColor": { 722 | "__type__": "cc.Color", 723 | "r": 214, 724 | "g": 214, 725 | "b": 214, 726 | "a": 255 727 | }, 728 | "_hoverColor": { 729 | "__type__": "cc.Color", 730 | "r": 211, 731 | "g": 211, 732 | "b": 211, 733 | "a": 255 734 | }, 735 | "_pressedColor": { 736 | "__type__": "cc.Color", 737 | "r": 255, 738 | "g": 255, 739 | "b": 255, 740 | "a": 255 741 | }, 742 | "_disabledColor": { 743 | "__type__": "cc.Color", 744 | "r": 124, 745 | "g": 124, 746 | "b": 124, 747 | "a": 255 748 | }, 749 | "_normalSprite": { 750 | "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", 751 | "__expectedType__": "cc.SpriteFrame" 752 | }, 753 | "_hoverSprite": { 754 | "__uuid__": "20835ba4-6145-4fbc-a58a-051ce700aa3e@f9941", 755 | "__expectedType__": "cc.SpriteFrame" 756 | }, 757 | "_pressedSprite": { 758 | "__uuid__": "544e49d6-3f05-4fa8-9a9e-091f98fc2ce8@f9941", 759 | "__expectedType__": "cc.SpriteFrame" 760 | }, 761 | "_disabledSprite": { 762 | "__uuid__": "951249e0-9f16-456d-8b85-a6ca954da16b@f9941", 763 | "__expectedType__": "cc.SpriteFrame" 764 | }, 765 | "_duration": 0.1, 766 | "_zoomScale": 1.2, 767 | "_target": { 768 | "__id__": 15 769 | }, 770 | "_id": "dbwZF9plpCQo101aQNz4Cd" 771 | }, 772 | { 773 | "__type__": "cc.ClickEvent", 774 | "target": { 775 | "__id__": 7 776 | }, 777 | "component": "", 778 | "_componentId": "5c687YB9CJA2J2+/JYuJNuq", 779 | "handler": "onButtonClicked", 780 | "customEventData": "" 781 | }, 782 | { 783 | "__type__": "cc.UITransform", 784 | "_name": "", 785 | "_objFlags": 0, 786 | "node": { 787 | "__id__": 12 788 | }, 789 | "_enabled": true, 790 | "__prefab": null, 791 | "_contentSize": { 792 | "__type__": "cc.Size", 793 | "width": 960, 794 | "height": 640 795 | }, 796 | "_anchorPoint": { 797 | "__type__": "cc.Vec2", 798 | "x": 0.5, 799 | "y": 0.5 800 | }, 801 | "_id": "c3tEI0R5NHh419zuw8/BgY" 802 | }, 803 | { 804 | "__type__": "cc.Canvas", 805 | "_name": "", 806 | "_objFlags": 0, 807 | "node": { 808 | "__id__": 12 809 | }, 810 | "_enabled": true, 811 | "__prefab": null, 812 | "_cameraComponent": { 813 | "__id__": 14 814 | }, 815 | "_alignCanvasWithScreen": true, 816 | "_id": "88k/+wm7pKZr5PZjoxAt+f" 817 | }, 818 | { 819 | "__type__": "cc.Widget", 820 | "_name": "", 821 | "_objFlags": 0, 822 | "node": { 823 | "__id__": 12 824 | }, 825 | "_enabled": true, 826 | "__prefab": null, 827 | "_alignFlags": 45, 828 | "_target": null, 829 | "_left": 0, 830 | "_right": 0, 831 | "_top": 0, 832 | "_bottom": 0, 833 | "_horizontalCenter": 0, 834 | "_verticalCenter": 0, 835 | "_isAbsLeft": true, 836 | "_isAbsRight": true, 837 | "_isAbsTop": true, 838 | "_isAbsBottom": true, 839 | "_isAbsHorizontalCenter": true, 840 | "_isAbsVerticalCenter": true, 841 | "_originalWidth": 0, 842 | "_originalHeight": 0, 843 | "_alignMode": 2, 844 | "_lockFlags": 0, 845 | "_id": "ebmGJFz01LDbCEBgCBtGDJ" 846 | }, 847 | { 848 | "__type__": "cc.SceneGlobals", 849 | "ambient": { 850 | "__id__": 27 851 | }, 852 | "shadows": { 853 | "__id__": 28 854 | }, 855 | "_skybox": { 856 | "__id__": 29 857 | }, 858 | "fog": { 859 | "__id__": 30 860 | } 861 | }, 862 | { 863 | "__type__": "cc.AmbientInfo", 864 | "_skyColor": { 865 | "__type__": "cc.Color", 866 | "r": 51, 867 | "g": 128, 868 | "b": 204, 869 | "a": 1 870 | }, 871 | "_skyIllum": 20000, 872 | "_groundAlbedo": { 873 | "__type__": "cc.Color", 874 | "r": 51, 875 | "g": 51, 876 | "b": 51, 877 | "a": 255 878 | } 879 | }, 880 | { 881 | "__type__": "cc.ShadowsInfo", 882 | "_type": 0, 883 | "_enabled": false, 884 | "_normal": { 885 | "__type__": "cc.Vec3", 886 | "x": 0, 887 | "y": 1, 888 | "z": 0 889 | }, 890 | "_distance": 0, 891 | "_shadowColor": { 892 | "__type__": "cc.Color", 893 | "r": 76, 894 | "g": 76, 895 | "b": 76, 896 | "a": 255 897 | }, 898 | "_fixedArea": false, 899 | "_pcf": 0, 900 | "_bias": 0.00001, 901 | "_normalBias": 0, 902 | "_near": 0.1, 903 | "_far": 10, 904 | "_shadowDistance": 100, 905 | "_invisibleOcclusionRange": 200, 906 | "_orthoSize": 5, 907 | "_maxReceived": 4, 908 | "_size": { 909 | "__type__": "cc.Vec2", 910 | "x": 512, 911 | "y": 512 912 | }, 913 | "_saturation": 0.75 914 | }, 915 | { 916 | "__type__": "cc.SkyboxInfo", 917 | "_envmap": null, 918 | "_isRGBE": false, 919 | "_enabled": false, 920 | "_useIBL": false 921 | }, 922 | { 923 | "__type__": "cc.FogInfo", 924 | "_type": 0, 925 | "_fogColor": { 926 | "__type__": "cc.Color", 927 | "r": 200, 928 | "g": 200, 929 | "b": 200, 930 | "a": 255 931 | }, 932 | "_enabled": false, 933 | "_fogDensity": 0.3, 934 | "_fogStart": 0.5, 935 | "_fogEnd": 300, 936 | "_fogAtten": 5, 937 | "_fogTop": 1.5, 938 | "_fogRange": 1.2 939 | } 940 | ] -------------------------------------------------------------------------------- /assets/Scenes/TestJump.scene.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.32", 3 | "importer": "scene", 4 | "imported": true, 5 | "uuid": "18134532-7de1-40a6-beee-e26fe8e7bb26", 6 | "files": [ 7 | ".json" 8 | ], 9 | "subMetas": {}, 10 | "userData": {} 11 | } 12 | -------------------------------------------------------------------------------- /assets/Scripts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "1.1.0", 3 | "importer": "directory", 4 | "imported": true, 5 | "uuid": "c03ae35c-4c4b-4548-a80d-eca65f9e86ba", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": { 9 | "compressionType": {}, 10 | "isRemoteBundle": {} 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /assets/Scripts/TestJump.ts: -------------------------------------------------------------------------------- 1 | 2 | import { _decorator, Component, Node, Vec3, Camera } from 'cc'; 3 | const { ccclass, property } = _decorator; 4 | 5 | 6 | @ccclass('TestJump') 7 | export class TestJump extends Component { 8 | 9 | @property({type: Node}) 10 | public testCube: Node; 11 | 12 | @property({type: Camera}) 13 | public testCamera: Camera; 14 | 15 | 16 | start () { 17 | // [3] 18 | } 19 | 20 | // update (deltaTime: number) { 21 | // // [4] 22 | // } 23 | 24 | public onButtonClicked() { 25 | this.testCube.position = Vec3.ZERO; 26 | // this.testCube.qtPosition(new Vec3(0, 1, 1), 1) 27 | // this.testCube.qtJumpPosition(new Vec3(3, 0, 0), 3, 1, 1) 28 | // .then(this.testCube.qtJumpPosition(new Vec3(0, 0, 0), 3, 1, 1)).union().repeat(5).start(); 29 | // this.testCube.qtJumpPosition(new Vec3(3, 1, 0), 3, 2, 2, { 30 | // onComplete: ()=> { 31 | // console.log('end'); 32 | // } 33 | // }).start(); 34 | // this.testCube.qtPunchScale(new Vec3(1, 1, 1), 1, { 35 | // onStart: ()=> { 36 | // console.log('begin'); 37 | // }, 38 | // onComplete: ()=> { 39 | // console.log('end'); 40 | // } 41 | // }).start(); 42 | // this.testCube.qtShakePosition(1, 1).start(); 43 | this.testCamera.qtShakePosition(new Vec3(0.1, 0.1, 0), 1, { 44 | onStart: ()=> { 45 | console.log('begin'); 46 | }, 47 | onComplete: ()=> { 48 | console.log('end'); 49 | } 50 | }).start(); 51 | // this.testCube.qtShakeRotation(1, 90).start(); 52 | // this.testCube.qtShakeScale(1, 1).start(); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /assets/Scripts/TestJump.ts.meta: -------------------------------------------------------------------------------- 1 | { 2 | "ver": "4.0.22", 3 | "importer": "typescript", 4 | "imported": true, 5 | "uuid": "5c687601-f422-40d8-9dbe-fc962e24dbaa", 6 | "files": [], 7 | "subMetas": {}, 8 | "userData": {} 9 | } 10 | -------------------------------------------------------------------------------- /imgs/jump.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gameall3d/QuickTween/d304f98b59f51d152ec15a6f15d6f3bbd2b52451/imgs/jump.gif -------------------------------------------------------------------------------- /imgs/punch_scale.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gameall3d/QuickTween/d304f98b59f51d152ec15a6f15d6f3bbd2b52451/imgs/punch_scale.gif -------------------------------------------------------------------------------- /imgs/shake_rotation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gameall3d/QuickTween/d304f98b59f51d152ec15a6f15d6f3bbd2b52451/imgs/shake_rotation.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "QuickTween", 3 | "type": "3d", 4 | "uuid": "03bcf456-910a-4666-8099-87b21051306d", 5 | "version": "3.3.2", 6 | "creator": { 7 | "version": "3.3.2" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /settings/v2/packages/builder.json: -------------------------------------------------------------------------------- 1 | { 2 | "__version__": "1.2.9" 3 | } 4 | -------------------------------------------------------------------------------- /settings/v2/packages/cocos-service.json: -------------------------------------------------------------------------------- 1 | { 2 | "game": { 3 | "name": "UNKNOW GAME", 4 | "app_id": "UNKNOW", 5 | "c_id": "0" 6 | }, 7 | "appConfigMaps": [ 8 | { 9 | "app_id": "UNKNOW", 10 | "config_id": "0c39c6" 11 | } 12 | ], 13 | "configs": [ 14 | { 15 | "app_id": "UNKNOW", 16 | "config_id": "0c39c6", 17 | "config_name": "Default", 18 | "config_remarks": "", 19 | "services": [] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /settings/v2/packages/device.json: -------------------------------------------------------------------------------- 1 | { 2 | "__version__": "1.0.1" 3 | } 4 | -------------------------------------------------------------------------------- /settings/v2/packages/engine.json: -------------------------------------------------------------------------------- 1 | { 2 | "__version__": "1.0.5" 3 | } 4 | -------------------------------------------------------------------------------- /settings/v2/packages/program.json: -------------------------------------------------------------------------------- 1 | { 2 | "__version__": "1.0.0" 3 | } 4 | -------------------------------------------------------------------------------- /settings/v2/packages/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "__version__": "1.0.1" 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | /* Base configuration. Do not edit this field. */ 3 | "extends": "./temp/tsconfig.cocos.json", 4 | 5 | /* Add your custom configuration here. */ 6 | "compilerOptions": { 7 | "strict": false 8 | } 9 | } 10 | --------------------------------------------------------------------------------