ResUtil.ts 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import { _decorator, Asset, Component, Constructor, director, Node, Prefab, SceneAsset, Sprite, SpriteFrame, tween, v2, v3 } from 'cc';
  2. import { Utils } from './Utils';
  3. import { Constants } from '../data/Constants';
  4. import { bundleMgr } from '../core/manager/BundleManager';
  5. import { Logger } from '../extend/Logger';
  6. import { PoolManager } from '../core/manager/PoolManager';
  7. import { uiMgr } from '../core/manager/UIManager';
  8. const { ccclass, property } = _decorator;
  9. export enum ITEM_TYPE {
  10. Diamond = "diamond",//钻石
  11. Coin = "coin",//金币
  12. Boomerang = "boomerang",//飞镖
  13. }
  14. @ccclass('ResUtil')
  15. export class ResUtil {
  16. /**
  17. * 设置精灵贴图 只能prefabs包 texture目录下
  18. * @param path 资源路径
  19. * 只能是在prefabs这个bundle目录下、然后如果使用
  20. * @param target 精灵或者节点
  21. * @param cb 回调函数
  22. */
  23. public static setSpriteFrame(name: string, target: Sprite | Node) {
  24. if(Utils.isNull(name))return;
  25. const path:string = `texture/${name}/spriteFrame`;
  26. bundleMgr.loadAsset(Constants.bundleName.prefabs,path,SpriteFrame, (err: Error, clip: SpriteFrame) => {
  27. if(!err) {
  28. let sprite: Sprite = target instanceof Node ? target.getComponent(Sprite) : target;
  29. if (!sprite) {
  30. console.error('Target node does not have a Sprite component!');
  31. }else{
  32. sprite.spriteFrame = clip;
  33. }
  34. }
  35. });
  36. }
  37. /**
  38. * 设置精灵贴图 指定自定义的包
  39. * @param bundle 包名如果传空 默认prefabs包名
  40. * @param path 路径 如果在prefabs包下,就可以直接传递传图片名称或者path路径(hit_m or texture/hit_m/spriteFrame)
  41. * 如果不在prefabs包下就只能传递完成的路径(texture/hit_m/spriteFrame)
  42. * @param type 类型
  43. * @param target 图片或者节点
  44. * @param onComplete 设置完成的回调
  45. */
  46. public static setSpriteFrameAsset(
  47. bundle: string,
  48. path: string,
  49. type: Constructor<Asset>,
  50. target: Sprite | Node,
  51. onComplete?: (err: Error | null, asset?: any) => void){
  52. if(Utils.isNull(bundle)){
  53. bundle = Constants.bundleName.prefabs;
  54. if(!path.startsWith("texture/")){
  55. path = `texture/${path}/spriteFrame`;
  56. }
  57. }
  58. if(Utils.isNull(path))return;
  59. bundleMgr.loadAsset(bundle,path,type, (err: Error, clip: SpriteFrame) => {
  60. if(!err) {
  61. let sprite: Sprite = target instanceof Node ? target.getComponent(Sprite) : target;
  62. if (!sprite) {
  63. console.error('Target node does not have a Sprite component!');
  64. }else{
  65. sprite.spriteFrame = clip;
  66. }
  67. }
  68. onComplete?.(err,clip);
  69. });
  70. }
  71. /**
  72. * 预加载场景资源(支持进度回调)
  73. * @param {string} sceneName - 场景名称(如 "main" 或者"level1")
  74. * @param {Function} [onComplete] - 完成回调
  75. * @param {Function} [onProgress] - 加载进度回调
  76. * @param {Error | null} onProgress.err - 错误信息(成功时为 null)
  77. * @param {number} onProgress.progress - 加载进度(0~1)
  78. */
  79. public static preloadScene(
  80. sceneName: string,
  81. onComplete?: () => void,
  82. onProgress?: (err: Error | null, progress: number) => void
  83. ): void {
  84. if (Utils.isNull(sceneName)) {
  85. Logger.warn("[SceneLoader] Scene name cannot be null or empty!");
  86. return;
  87. }//开始预加载场景
  88. director.preloadScene(
  89. sceneName,
  90. (loadedCount: number, totalCount: number) => {//进度更新回调
  91. const progress = totalCount > 0 ? loadedCount / totalCount : 0;
  92. onProgress?.(null, progress); // 通知进度(未完成)
  93. },//加载完成回调
  94. (error: Error | null, sceneAsset?: SceneAsset) => {
  95. if (error) {
  96. Logger.error(`[SceneLoader] Failed to preload scene "${sceneName}":`, error);
  97. onProgress?.(error,0); // 通知失败
  98. return;
  99. }
  100. onComplete?.();
  101. //预加载成功
  102. Logger.log(`[SceneLoader] Scene "${sceneName}" preloaded successfully`);
  103. onProgress?.(null, 1);
  104. }
  105. );
  106. }
  107. /**
  108. * 加载敌人的预制体
  109. * @param name 敌人的名字
  110. * @param parent 父节点
  111. * @returns 返回一个敌人
  112. */
  113. public static loadEnemyRes(name: string, parent?: Node): Promise<Node | null> {
  114. return new Promise(async (resolve, reject) => {
  115. try {
  116. if(Utils.isNull(name)) {
  117. resolve(null);
  118. return;
  119. }
  120. //加载资源
  121. const path = `enemy/${name}`;
  122. const res = await bundleMgr.loadAsset(Constants.bundleName.prefabs, path, Prefab) as Prefab;
  123. //从对象池获取实例
  124. const enemy = PoolManager.getNode(res) as Node;
  125. //设置父节点
  126. if (parent) {
  127. enemy.parent = parent;
  128. }
  129. //返回结果
  130. resolve(enemy);
  131. } catch (error) {
  132. Logger.error(`[loadEnemyRes] 加载敌人资源失败: ${name}`, error);
  133. reject(new Error(`加载敌人资源失败: ${name}`));
  134. }
  135. });
  136. }
  137. /**
  138. * 加载枪的预制体
  139. * @param name 枪的名称
  140. * @param parent 父节点
  141. * @returns 返回一把枪
  142. */
  143. public static async loadGunRes(path: string,parent?: Node){
  144. return new Promise(async (resolve, reject) => {
  145. try {
  146. if(Utils.isNull(path)) {
  147. resolve(null);
  148. return;
  149. }
  150. const res: Prefab = await bundleMgr.loadAsset(Constants.bundleName.prefabs, path, Prefab) as Prefab;
  151. const gun: Node = PoolManager.getNode(res) as Node;
  152. if (parent) {
  153. gun.parent = parent;
  154. }
  155. resolve(gun);
  156. } catch (error) {
  157. Logger.error(`[loadGunRes] 加载枪资源失败: ${name}`, error);
  158. reject(error);
  159. }
  160. });
  161. }
  162. /**
  163. * 只加载prefabs资源ui和页面 预制体
  164. * @param name 名字 只能是预知体
  165. * @param parent 父节点
  166. * @returns 返回一个节点
  167. */
  168. public static loadRes(path: string, parent?: Node): Promise<Node | null> {
  169. return new Promise(async (resolve, reject) => {
  170. try {
  171. if (Utils.isNull(path)) {
  172. resolve(null);
  173. return;
  174. }
  175. //加载资源 从对象池获取实例
  176. const res = await bundleMgr.loadAsset(Constants.bundleName.prefabs, path, Prefab) as Prefab;
  177. const n = PoolManager.getNode(res) as Node;
  178. //设置父节点
  179. if (parent) {
  180. n.parent = parent;
  181. }
  182. //返回结果
  183. resolve(n);
  184. } catch (error) {
  185. console.error(`加载资源失败: ${path}`, error);
  186. reject(new Error(`加载资源失败:: ${path}`));
  187. }
  188. });
  189. }
  190. /**
  191. * 购买金币和钻石的动画
  192. * @param type
  193. * @param starNode
  194. * @param targetNode
  195. * @param count
  196. * @param radius
  197. * @param callback
  198. */
  199. public static async flyAnim(type: ITEM_TYPE, starNode: Node, targetNode: Node, count: number, radius: number, callback: Function) {
  200. let getPoint = (r, ox, oy, count) => {
  201. var point = []; //结果
  202. var radians = (Math.PI / 180) * Math.round(360 / count), //弧度
  203. i = 0;
  204. for (; i < count; i++) {
  205. var x = ox + r * Math.sin(radians * i),
  206. y = oy + r * Math.cos(radians * i);
  207. point.unshift(v2(x, y)); //为保持数据顺时针
  208. }
  209. return point;
  210. }
  211. let start = starNode.worldPosition;
  212. var array = getPoint(radius, start.x, start.y, count);
  213. var nodeArray = new Array();
  214. for (var i = 0; i < array.length; i++) {
  215. let ret: any = await bundleMgr.loadAsset(Constants.bundleName.prefabs, `items/${type}`, Prefab);
  216. var gold = PoolManager.getNode(ret);
  217. gold.setWorldScale(v3(0.7, 0.7, 0.7));
  218. gold.parent = uiMgr.getCurentSceneRoot();
  219. var randPos = v3(array[i].x + Utils.getRandomInt(0, 50), array[i].y + Utils.getRandomInt(0, 50), 1);
  220. gold.setWorldPosition(start);
  221. nodeArray.push({ gold, randPos });
  222. }
  223. var notPlay = false;
  224. let dstPos = targetNode.worldPosition.clone();
  225. for (let i = 0; i < nodeArray.length; i++) {
  226. let pos = nodeArray[i].randPos;
  227. let node = nodeArray[i].gold;
  228. nodeArray[i].gold.id = i;
  229. tween(node)
  230. .to(0.2, { worldPosition: pos })
  231. .delay(i * 0.03)
  232. .to(0.7, { worldPosition: v3(dstPos.x, dstPos.y, 1) })
  233. .call(() => {
  234. if(!notPlay) {
  235. notPlay = true;
  236. tween(targetNode)
  237. .to(0.1, { scale: v3(2, 2, 2) })
  238. .to(0.1, { scale: v3(1, 1, 1) })
  239. .call(() => {
  240. notPlay = false;
  241. }).start()
  242. }
  243. let idx: number = node["_id"];
  244. callback(idx == nodeArray.length - 1);
  245. PoolManager.putNode(node);
  246. })
  247. .start()
  248. }
  249. }
  250. }