export class LoadProgress { public url: string; public completedCount: number; public totalCount: number; public item: any; public cb?: Function; } /** 一些cocos api 的封装, promise函数统一加上sync后缀 */ export default class CocosHelper { public static async callInNextTick() { return new Promise((resolve, reject) => { setTimeout(() => { resolve(true); }, 0); }) } /** 加载进度 */ public static loadProgress = new LoadProgress(); /** 等待时间, 秒为单位 */ public static sleepSync = function(dur: number): Promise { return new Promise((resolve, reject) => { cc.Canvas.instance.scheduleOnce(() => { resolve(true); }, dur); }); } /** * * @param target * @param repeat -1,表示永久执行 * @param tweens */ public static async runRepeatTweenSync(target: any, repeat: number, ...tweens: cc.Tween[]) { return new Promise((resolve, reject) => { let selfTween = cc.tween(target); for(const tmpTween of tweens) { selfTween = selfTween.then(tmpTween); } if(repeat < 0) { cc.tween(target).repeatForever(selfTween).start(); }else { cc.tween(target).repeat(repeat, selfTween).call(() => { resolve(true); }).start(); } }); } /** 同步的tween */ public static async runTweenSync(target: any, ...tweens: cc.Tween[]): Promise { return new Promise((resolve, reject) => { let selfTween = cc.tween(target); for(const tmpTween of tweens) { selfTween = selfTween.then(tmpTween); } selfTween.call(() => { resolve(); }).start(); }); } /** 停止tween */ public stopTween(target: any) { cc.Tween.stopAllByTarget(target); } public stopTweenByTag(tag: number) { cc.Tween.stopAllByTag(tag); } /** 同步的动作, 在2.4.x action已经被废弃了, 不建议使用 */ public static async runActionSync(node: cc.Node, ...actions: cc.FiniteTimeAction[]) { if(!actions || actions.length <= 0) return ; return new Promise((resolve, reject) => { actions.push(cc.callFunc(() => { resolve(true); })); node.runAction(cc.sequence(actions)); }); } /** 同步的动画 */ public static async runAnimSync(node: cc.Node, animName?: string | number) { let anim = node.getComponent(cc.Animation); if(!anim) return ; let clip: cc.AnimationClip = null; if(!animName) clip = anim.defaultClip; else { let clips = anim.getClips(); if(typeof(animName) === "number") { clip = clips[animName]; }else if(typeof(animName) === "string") { for(let i=0; i(url: string, type: typeof cc.Asset, onProgress?: (completedCount: number, totalCount: number, item: any) => void): Promise { return null; } private static _loadingMap: {[key: string]: Function[]} = {}; public static loadRes(url: string, type: typeof cc.Asset, callback: Function ) { if(this._loadingMap[url]) { this._loadingMap[url].push(callback); return ; } this._loadingMap[url] = [callback]; this.loadResSync(url, type).then((data: any) => { let arr = this._loadingMap[url]; for(const func of arr) { func(data); } this._loadingMap[url] = null; delete this._loadingMap[url]; }); } /** 加载资源 */ public static loadResSync(url: string, type: typeof cc.Asset, onProgress?: (completedCount: number, totalCount: number, item: any) => void): Promise{ return new Promise((resolve, reject) => { if(!onProgress) onProgress = this._onProgress; cc.resources.load(url, type, onProgress, (err, asset: any) => { if (err) { cc.error(`${url} [资源加载] 错误 ${err}`); resolve(null); }else { resolve(asset); } }); }); } /** * 加载进度 * cb方法 其实目的是可以将loader方法的progress */ private static _onProgress(completedCount: number, totalCount: number, item: any) { CocosHelper.loadProgress.completedCount = completedCount; CocosHelper.loadProgress.totalCount = totalCount; CocosHelper.loadProgress.item = item; CocosHelper.loadProgress.cb && CocosHelper.loadProgress.cb(completedCount, totalCount, item); } /** * 寻找子节点 */ public static findChildInNode(nodeName: string, rootNode: cc.Node): cc.Node { if(rootNode.name == nodeName) { return rootNode; } for(let i=0; i$/); if(arr && arr.length > 0) { return arr[0].slice(1, -1); } return com.name; } /** 加载bundle */ public static loadBundleSync(url: string, options: any): Promise { return new Promise((resolve, reject) => { cc.assetManager.loadBundle(url, options, (err: Error, bundle: cc.AssetManager.Bundle) => { if(!err) { cc.error(`加载bundle失败, url: ${url}, err:${err}`); resolve(null); }else { resolve(bundle); } }); }); } /** 路径是相对分包文件夹路径的相对路径 */ public static loadAssetFromBundleSync(bundleName: string, url: string) { let bundle = cc.assetManager.getBundle(bundleName); if(!bundle) { cc.error(`加载bundle中的资源失败, 未找到bundle, bundleUrl:${bundleName}`); return null; } return new Promise((resolve, reject) => { bundle.load(url, (err, asset: cc.Asset | cc.Asset[]) => { if(err) { cc.error(`加载bundle中的资源失败, 未找到asset, url:${url}, err:${err}`); resolve(null); }else { resolve(asset); } }); }); } /** 通过路径加载资源, 如果这个资源在bundle内, 会先加载bundle, 在解开bundle获得对应的资源 */ public static loadAssetSync(url: string) { return new Promise((resolve, reject) => { cc.resources.load(url, (err, assets: cc.Asset | cc.Asset[]) => { if(!err) { cc.error(`加载asset失败, url:${url}, err: ${err}`); resolve(null); }else { this.addRef(assets); resolve(assets); } }); }); } /** 释放资源 */ public static releaseAsset(assets: cc.Asset | cc.Asset[]) { this.decRes(assets); } /** 增加引用计数 */ private static addRef(assets: cc.Asset | cc.Asset[]) { if(assets instanceof Array) { for(const a of assets) { a.addRef(); } }else { assets.addRef(); } } /** 减少引用计数, 当引用计数减少到0时,会自动销毁 */ private static decRes(assets: cc.Asset | cc.Asset[]) { if(assets instanceof Array) { for(const a of assets) { a.decRef(); } }else { assets.decRef(); } } /** 截图 */ public static captureScreen(camera: cc.Camera, prop?: cc.Node | cc.Rect) { let newTexture = new cc.RenderTexture(); let oldTexture = camera.targetTexture; let rect: cc.Rect = cc.rect(0, 0, cc.visibleRect.width, cc.visibleRect.height); if(prop) { if(prop instanceof cc.Node) { rect = prop.getBoundingBoxToWorld(); }else { rect = prop; } } newTexture.initWithSize(cc.visibleRect.width, cc.visibleRect.height, cc.game['_renderContext'].STENCIL_INDEX8); camera.targetTexture = newTexture; camera.render(); camera.targetTexture = oldTexture; let buffer = new ArrayBuffer(rect.width * rect.height * 4); let data = new Uint8Array(buffer); newTexture.readPixels(data, rect.x, rect.y, rect.width, rect.height); return data; } public static tweenFloat(from: number, to: number, duration: number, onUpdate: (t: number) => void, onComplete?: Function, autoStart: boolean = true) { let o: Record = { _value: from }; Object.defineProperty(o, 'value', { get: () => o._value, set: (v: number) => { o._value = v; onUpdate && onUpdate(o._value); }, }); let tween = cc.tween(o).to(duration, { value: to }).call(onComplete); if (autoStart) { tween.start(); } return tween; } public static tweenVec2(from: cc.Vec2, to: cc.Vec2, duration: number, onUpdate: (t: cc.Vec2) => void, onComplete?: Function, autoStart: boolean = true) { let o: Record = {_value: from}; Object.defineProperty(o, 'value', { get: () => o._value, set: (v: cc.Vec2) => { o._value = v; onUpdate && onUpdate(o._value); }, }); let tween = cc.tween(o).to(duration, { value: to }).call(onComplete); if (autoStart) { tween.start(); } return tween; } }