59c9a449918b535a4c703ec0f09f091f198a0d28.js 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692
  1. System.register(["__unresolved_0", "cc", "__unresolved_1"], function (_export, _context) {
  2. "use strict";
  3. var _reporterNs, _cclegacy, __checkObsolete__, __checkObsoleteInNamespace__, UITransform, Vec2, Vec3, _decorator, find, director, Color, UIOpacity, tween, view, Quat, math, sensitiveArray, _dec, _class, _crd, ccclass, property, Utils;
  4. function _reportPossibleCrUseOfsensitiveArray(extras) {
  5. _reporterNs.report("sensitiveArray", "../extend/SensitiveWords", _context.meta, extras);
  6. }
  7. return {
  8. setters: [function (_unresolved_) {
  9. _reporterNs = _unresolved_;
  10. }, function (_cc) {
  11. _cclegacy = _cc.cclegacy;
  12. __checkObsolete__ = _cc.__checkObsolete__;
  13. __checkObsoleteInNamespace__ = _cc.__checkObsoleteInNamespace__;
  14. UITransform = _cc.UITransform;
  15. Vec2 = _cc.Vec2;
  16. Vec3 = _cc.Vec3;
  17. _decorator = _cc._decorator;
  18. find = _cc.find;
  19. director = _cc.director;
  20. Color = _cc.Color;
  21. UIOpacity = _cc.UIOpacity;
  22. tween = _cc.tween;
  23. view = _cc.view;
  24. Quat = _cc.Quat;
  25. math = _cc.math;
  26. }, function (_unresolved_2) {
  27. sensitiveArray = _unresolved_2.default;
  28. }],
  29. execute: function () {
  30. _crd = true;
  31. _cclegacy._RF.push({}, "a9261Lh275Io6NmeAOMUfdP", "Utils", undefined);
  32. __checkObsolete__(['UITransform', 'Vec2', 'Vec3', 'Node', '_decorator', 'find', 'director', 'Color', 'UIOpacity', 'tween', 'Label', 'Camera', 'view', 'Quat', 'math']);
  33. ({
  34. ccclass,
  35. property
  36. } = _decorator);
  37. _export("Utils", Utils = (_dec = ccclass("Utils"), _dec(_class = class Utils {
  38. /**
  39. * 验证字符串是否是空的
  40. * @s 字符串
  41. */
  42. static isNull(s) {
  43. if (s == "" || s == null || s == undefined) {
  44. return true;
  45. }
  46. if (typeof s === 'string') {
  47. var re = new RegExp("^[ ]+$");
  48. return re.test(s);
  49. } else {
  50. return false;
  51. }
  52. }
  53. /**
  54. * 合并多个字典
  55. * @param args
  56. */
  57. static merge() {
  58. var mergeFn = (arg1, arg2) => {
  59. var res = {};
  60. res = Object.assign(arg1, arg2);
  61. return res;
  62. };
  63. var nDict = {};
  64. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  65. args[_key] = arguments[_key];
  66. }
  67. args.forEach(obj => {
  68. nDict = mergeFn(nDict, obj);
  69. });
  70. return nDict;
  71. }
  72. /**
  73. * 排除合并对象,但排除'reward'和'dec'属性(如果e中已存在)
  74. * mergeWithExceptions(e, pData, ['reward', 'dec']);
  75. * @param target
  76. * @param source
  77. * @param exclude
  78. * @returns
  79. */
  80. static mergeWithExceptions(target, source, exclude) {
  81. Object.keys(source).forEach(key => {
  82. if (!exclude.includes(key) || !(key in target)) {
  83. target[key] = source[key];
  84. }
  85. });
  86. return target;
  87. }
  88. /**
  89. * 深度拷贝
  90. * @param {any} sObj 拷贝的对象
  91. * @returns
  92. */
  93. static clone(sObj) {
  94. if (sObj === null || typeof sObj !== "object") {
  95. return sObj;
  96. }
  97. var s = {};
  98. if (sObj.constructor === Array) {
  99. s = [];
  100. }
  101. for (var i in sObj) {
  102. if (sObj.hasOwnProperty(i)) {
  103. s[i] = this.clone(sObj[i]);
  104. }
  105. }
  106. return s;
  107. }
  108. /**
  109. * 转换数字
  110. */
  111. static formatUnits(num) {
  112. if (num >= 1e8) {
  113. return (num / 1e8).toFixed(1) + '亿';
  114. } else if (num >= 1e7) {
  115. return (num / 1e7).toFixed(1) + '千万';
  116. } else if (num >= 1e6) {
  117. return (num / 1e6).toFixed(1) + '百万';
  118. } else if (num >= 1e4) {
  119. return (num / 1e4).toFixed(1) + '万';
  120. } else if (num >= 1000) {
  121. return (num / 1000).toFixed(1) + 'k';
  122. } else {
  123. return num.toString();
  124. }
  125. }
  126. /**
  127. * 将object转化为数组
  128. * @param { any} srcObj
  129. * @returns
  130. */
  131. static objectToArray(srcObj) {
  132. var resultArr = []; // to array
  133. for (var _key2 in srcObj) {
  134. if (!srcObj.hasOwnProperty(_key2)) {
  135. continue;
  136. }
  137. resultArr.push(srcObj[_key2]);
  138. }
  139. return resultArr;
  140. }
  141. /**
  142. * !#zh 将数组转化为object。
  143. */
  144. /**
  145. * 将数组转化为object。
  146. * @param { any} srcObj
  147. * @param { string} objectKey
  148. * @returns
  149. */
  150. static arrayToObject(srcObj, objectKey) {
  151. var resultObj = {}; // to object
  152. for (var key in srcObj) {
  153. if (!srcObj.hasOwnProperty(key) || !srcObj[key][objectKey]) {
  154. continue;
  155. }
  156. resultObj[srcObj[key][objectKey]] = srcObj[key];
  157. }
  158. return resultObj;
  159. }
  160. /**
  161. * 根据权重,计算随机内容
  162. * @param {arrany} weightArr
  163. * @param {number} totalWeight 权重
  164. * @returns
  165. */
  166. static getWeightRandIndex(weightArr, totalWeight) {
  167. var randWeight = Math.floor(Math.random() * totalWeight);
  168. var sum = 0;
  169. for (var weightIndex = 0; weightIndex < weightArr.length; weightIndex++) {
  170. sum += weightArr[weightIndex];
  171. if (randWeight < sum) {
  172. break;
  173. }
  174. }
  175. return weightIndex;
  176. }
  177. /**
  178. * 从n个数中获取m个随机数
  179. * @param {Number} n 总数
  180. * @param {Number} m 获取数
  181. * @returns {Array} array 获取数列
  182. */
  183. static getRandomNFromM(n, m) {
  184. var array = [];
  185. var intRd = 0;
  186. var count = 0;
  187. while (count < m) {
  188. if (count >= n + 1) {
  189. break;
  190. }
  191. intRd = this.getRandomInt(0, n);
  192. var flag = 0;
  193. for (var i = 0; i < count; i++) {
  194. if (array[i] === intRd) {
  195. flag = 1;
  196. break;
  197. }
  198. }
  199. if (flag === 0) {
  200. array[count] = intRd;
  201. count++;
  202. }
  203. }
  204. return array;
  205. }
  206. /**
  207. * 获取随机整数
  208. * @param {Number} min 最小值
  209. * @param {Number} max 最大值
  210. * @returns
  211. */
  212. static getRandomInt(min, max) {
  213. var r = Math.random();
  214. var rr = r * (max - min + 1) + min;
  215. return Math.floor(rr);
  216. }
  217. /**
  218. * 获取字符串长度
  219. * @param {string} render
  220. * @returns
  221. */
  222. static getStringLength(render) {
  223. var strArr = render;
  224. var len = 0;
  225. for (var i = 0, n = strArr.length; i < n; i++) {
  226. var val = strArr.charCodeAt(i);
  227. if (val <= 255) {
  228. len = len + 1;
  229. } else {
  230. len = len + 2;
  231. }
  232. }
  233. return Math.ceil(len / 2);
  234. }
  235. /**
  236. * 要从一个数组模型中随机取出 n 个元素
  237. * @param arr
  238. * @param n
  239. * @returns 返回一个新的数组
  240. */
  241. static getRandomElements(arr, n) {
  242. if (n <= 0) return []; // 如果 n 小于等于 0,返回空数组
  243. //复制数组以避免修改原数组
  244. var copy = [...arr]; //Fisher-Yates 洗牌算法
  245. for (var i = copy.length - 1; i > 0; i--) {
  246. var j = Math.floor(Math.random() * (i + 1));
  247. [copy[i], copy[j]] = [copy[j], copy[i]];
  248. } //如果 n 超过数组长度,返回乱序后的整个数组
  249. if (n >= copy.length) {
  250. return copy;
  251. } //返回前 n 个元素
  252. return copy.slice(0, n);
  253. }
  254. /**
  255. * 判断传入的参数是否为空的Object。数组或undefined会返回false
  256. * @param obj
  257. */
  258. static isEmptyObject(obj) {
  259. var result = true;
  260. if (obj && obj.constructor === Object) {
  261. for (var key in obj) {
  262. if (obj.hasOwnProperty(key)) {
  263. result = false;
  264. break;
  265. }
  266. }
  267. } else {
  268. result = false;
  269. }
  270. return result;
  271. }
  272. /**
  273. * 判断是否是新的一天
  274. * @param {Object|Number} dateValue 时间对象 todo MessageCenter 与 pve 相关的时间存储建议改为 Date 类型
  275. * @returns {boolean}
  276. */
  277. static isNewDay(dateValue) {
  278. // todo:是否需要判断时区?
  279. var oldDate = new Date(dateValue);
  280. var curDate = new Date();
  281. var oldYear = oldDate.getYear();
  282. var oldMonth = oldDate.getMonth();
  283. var oldDay = oldDate.getDate();
  284. var curYear = curDate.getYear();
  285. var curMonth = curDate.getMonth();
  286. var curDay = curDate.getDate();
  287. if (curYear > oldYear) {
  288. return true;
  289. } else {
  290. if (curMonth > oldMonth) {
  291. return true;
  292. } else {
  293. if (curDay > oldDay) {
  294. return true;
  295. }
  296. }
  297. }
  298. return false;
  299. }
  300. /**
  301. * 获取对象属性数量
  302. * @param {object}o 对象
  303. * @returns
  304. */
  305. static getPropertyCount(o) {
  306. var n,
  307. count = 0;
  308. for (n in o) {
  309. if (o.hasOwnProperty(n)) {
  310. count++;
  311. }
  312. }
  313. return count;
  314. }
  315. /**
  316. * 返回一个差异化数组(将array中diff里的值去掉)
  317. * @param array
  318. * @param diff
  319. */
  320. static difference(array, diff) {
  321. var result = [];
  322. if (array.constructor !== Array || diff.constructor !== Array) {
  323. return result;
  324. }
  325. var length = array.length;
  326. for (var i = 0; i < length; i++) {
  327. if (diff.indexOf(array[i]) === -1) {
  328. result.push(array[i]);
  329. }
  330. }
  331. return result;
  332. }
  333. static _stringToArray(string) {
  334. // 用于判断emoji的正则们
  335. var rsAstralRange = '\\ud800-\\udfff';
  336. var rsZWJ = '\\u200d';
  337. var rsVarRange = '\\ufe0e\\ufe0f';
  338. var rsComboMarksRange = '\\u0300-\\u036f';
  339. var reComboHalfMarksRange = '\\ufe20-\\ufe2f';
  340. var rsComboSymbolsRange = '\\u20d0-\\u20ff';
  341. var rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;
  342. var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
  343. var rsFitz = '\\ud83c[\\udffb-\\udfff]';
  344. var rsOptVar = '[' + rsVarRange + ']?';
  345. var rsCombo = '[' + rsComboRange + ']';
  346. var rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')';
  347. var reOptMod = rsModifier + '?';
  348. var rsAstral = '[' + rsAstralRange + ']';
  349. var rsNonAstral = '[^' + rsAstralRange + ']';
  350. var rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}';
  351. var rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]';
  352. var rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*';
  353. var rsSeq = rsOptVar + reOptMod + rsOptJoin;
  354. var rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
  355. var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
  356. var hasUnicode = function hasUnicode(val) {
  357. return reHasUnicode.test(val);
  358. };
  359. var unicodeToArray = function unicodeToArray(val) {
  360. return val.match(reUnicode) || [];
  361. };
  362. var asciiToArray = function asciiToArray(val) {
  363. return val.split('');
  364. };
  365. return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
  366. } // 模拟传msg的uuid
  367. static simulationUUID() {
  368. function s4() {
  369. return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  370. }
  371. return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
  372. }
  373. static trim(str) {
  374. return str.replace(/(^\s*)|(\s*$)/g, "");
  375. }
  376. /**
  377. * 判断当前时间是否在有效时间内
  378. * @param {String|Number} start 起始时间。带有时区信息
  379. * @param {String|Number} end 结束时间。带有时区信息
  380. */
  381. static isNowValid(start, end) {
  382. var startTime = new Date(start);
  383. var endTime = new Date(end);
  384. var result = false;
  385. if (startTime.getDate() + '' !== 'NaN' && endTime.getDate() + '' !== 'NaN') {
  386. var curDate = new Date();
  387. result = curDate < endTime && curDate > startTime;
  388. }
  389. return result;
  390. }
  391. /**
  392. * 返回相隔天数
  393. * @param start
  394. * @param end
  395. * @returns
  396. */
  397. static getDeltaDays(start, end) {
  398. start = new Date(start);
  399. end = new Date(end);
  400. var startYear = start.getFullYear();
  401. var startMonth = start.getMonth() + 1;
  402. var startDate = start.getDate();
  403. var endYear = end.getFullYear();
  404. var endMonth = end.getMonth() + 1;
  405. var endDate = end.getDate();
  406. start = new Date(startYear + '/' + startMonth + '/' + startDate + ' GMT+0800').getTime();
  407. end = new Date(endYear + '/' + endMonth + '/' + endDate + ' GMT+0800').getTime();
  408. var deltaTime = end - start;
  409. return Math.floor(deltaTime / (24 * 60 * 60 * 1000));
  410. }
  411. /**
  412. * 获取数组最小值
  413. * @param array 数组
  414. * @returns
  415. */
  416. static getMin(array) {
  417. var result = null;
  418. if (array.constructor === Array) {
  419. var length = array.length;
  420. for (var i = 0; i < length; i++) {
  421. if (i === 0) {
  422. result = Number(array[0]);
  423. } else {
  424. result = result > Number(array[i]) ? Number(array[i]) : result;
  425. }
  426. }
  427. }
  428. return result;
  429. }
  430. /**
  431. * 格式化两位小数点
  432. * @param time
  433. * @returns
  434. */
  435. static formatTwoDigits(time) {
  436. //@ts-ignore
  437. return (Array(2).join(0) + time).slice(-2);
  438. }
  439. /**
  440. * 根据格式返回时间
  441. * @param date 时间
  442. * @param fmt 格式
  443. * @returns
  444. */
  445. static formatDate(date, fmt) {
  446. var o = {
  447. "M+": date.getMonth() + 1,
  448. //月份
  449. "d+": date.getDate(),
  450. //日
  451. "h+": date.getHours(),
  452. //小时
  453. "m+": date.getMinutes(),
  454. //分
  455. "s+": date.getSeconds(),
  456. //秒
  457. "q+": Math.floor((date.getMonth() + 3) / 3),
  458. //季度
  459. "S": date.getMilliseconds() //毫秒
  460. };
  461. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  462. for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
  463. return fmt;
  464. }
  465. /**
  466. * 获取格式化后的日期(不含小时分秒)
  467. */
  468. static getDay() {
  469. var date = new Date();
  470. return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
  471. }
  472. /**
  473. * 格式化名字,XXX...
  474. * @param {string} name 需要格式化的字符串
  475. * @param {number}limit
  476. * @returns {string} 返回格式化后的字符串XXX...
  477. */
  478. static formatName(name, limit) {
  479. limit = limit || 6;
  480. var nameArray = this._stringToArray(name);
  481. var str = '';
  482. var length = nameArray.length;
  483. if (length > limit) {
  484. for (var i = 0; i < limit; i++) {
  485. str += nameArray[i];
  486. }
  487. str += '...';
  488. } else {
  489. str = name;
  490. }
  491. return str;
  492. }
  493. /**
  494. * 格式化钱数,超过10000 转换位 10K 10000K 转换为 10M
  495. * @param {number}money 需要被格式化的数值
  496. * @returns {string}返回 被格式化的数值
  497. */
  498. static formatMoney(money) {
  499. var arrUnit = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'B', 'N', 'D'];
  500. var strValue = '';
  501. for (var idx = 0; idx < arrUnit.length; idx++) {
  502. if (money >= 10000) {
  503. money /= 1000;
  504. } else {
  505. strValue = Math.floor(money) + arrUnit[idx];
  506. break;
  507. }
  508. }
  509. if (strValue === '') {
  510. strValue = Math.floor(money) + 'U'; //超过最大值就加个U
  511. }
  512. return strValue;
  513. }
  514. /**
  515. * 开始展示文字
  516. * @param lable 文本
  517. * @param words 播放的文字
  518. * @param cb 播放完成回调
  519. * @param cbbS 回调延迟
  520. * @param delay 延迟逐字播放
  521. * @param s 一个字的播放速度/秒
  522. */
  523. static verbatim(lable, words, cb, cbbS, delay, s) {
  524. if (cbbS === void 0) {
  525. cbbS = 0;
  526. }
  527. if (delay === void 0) {
  528. delay = 0;
  529. }
  530. if (s === void 0) {
  531. s = 0.1;
  532. }
  533. if (!words.hasOwnProperty('length')) return;
  534. lable.node.active = true;
  535. lable.unscheduleAllCallbacks();
  536. var f = function f() {
  537. var arr = words.replace(/ /g, "").split('');
  538. var step = 0;
  539. var allWords = "";
  540. var fun = () => {
  541. allWords += arr[step];
  542. lable.string = allWords;
  543. if (++step >= arr.length) {
  544. lable.unschedule(fun);
  545. var cbFun = () => {
  546. cb == null || cb();
  547. };
  548. cbbS > 0 ? lable.scheduleOnce(cbFun, cbbS) : cbFun();
  549. }
  550. };
  551. lable.schedule(fun, s, Number.MAX_SAFE_INTEGER);
  552. };
  553. delay > 0 ? lable.scheduleOnce(f.bind(this), delay) : f();
  554. }
  555. /**
  556. * 格式化数值
  557. * @param {number}value 需要被格式化的数值
  558. * @returns {string}返回 被格式化的数值
  559. */
  560. static formatValue(value) {
  561. var arrUnit = [];
  562. var strValue = '';
  563. for (var i = 0; i < 26; i++) {
  564. arrUnit.push(String.fromCharCode(97 + i));
  565. }
  566. for (var idx = 0; idx < arrUnit.length; idx++) {
  567. if (value >= 10000) {
  568. value /= 1000;
  569. } else {
  570. strValue = Math.floor(value) + arrUnit[idx];
  571. break;
  572. }
  573. }
  574. return strValue;
  575. }
  576. /**
  577. * 根据剩余秒数格式化剩余时间 返回 HH:MM:SS
  578. * @param {Number} leftSec
  579. */
  580. static formatTimeForSecond(leftSec, withoutSeconds) {
  581. if (withoutSeconds === void 0) {
  582. withoutSeconds = false;
  583. }
  584. var timeStr = '';
  585. var sec = leftSec % 60;
  586. var leftMin = Math.floor(leftSec / 60);
  587. leftMin = leftMin < 0 ? 0 : leftMin;
  588. var hour = Math.floor(leftMin / 60);
  589. var min = leftMin % 60;
  590. if (hour > 0) {
  591. timeStr += hour > 9 ? hour.toString() : '0' + hour;
  592. timeStr += ':';
  593. } else {
  594. timeStr += '00:';
  595. }
  596. timeStr += min > 9 ? min.toString() : '0' + min;
  597. if (!withoutSeconds) {
  598. timeStr += ':';
  599. timeStr += sec > 9 ? sec.toString() : '0' + sec;
  600. }
  601. return timeStr;
  602. }
  603. /**
  604. * 计算 3D 空间中两点之间的欧几里得距离
  605. * @param a 第一个点
  606. * @param b 第二个点
  607. * @returns 两点之间的距离
  608. */
  609. static distance(a, b) {
  610. var dx = b.x - a.x;
  611. var dy = b.y - a.y;
  612. var dz = b.z - a.z;
  613. return Math.sqrt(dx * dx + dy * dy + dz * dz);
  614. }
  615. /**
  616. * 根据剩余毫秒数格式化剩余时间 返回 HH:MM:SS
  617. *
  618. * @param {Number} ms
  619. */
  620. static formatTimeForMillisecond(ms) {
  621. var second = Math.floor(ms / 1000 % 60);
  622. var minute = Math.floor(ms / 1000 / 60 % 60);
  623. var hour = Math.floor(ms / 1000 / 60 / 60);
  624. return {
  625. 'hour': hour,
  626. 'minute': minute,
  627. 'second': second
  628. };
  629. }
  630. /**
  631. * 格式化时间戳字符串
  632. * @param timestamp 1740006560000
  633. * @returns 输出2025-02-20 05:09:20
  634. */
  635. static formatTimestamp(timestamp) {
  636. var date = new Date(timestamp); //获取年月日时分秒
  637. var year = date.getFullYear(); //月份从 0 开始,需要 +1
  638. var month = String(date.getMonth() + 1).padStart(2, '0');
  639. var day = String(date.getDate()).padStart(2, '0');
  640. var hours = String(date.getHours()).padStart(2, '0');
  641. var minutes = String(date.getMinutes()).padStart(2, '0');
  642. var seconds = String(date.getSeconds()).padStart(2, '0'); //拼接成 YYYY-MM-DD HH:MM:SS 格式
  643. return year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
  644. }
  645. /**
  646. * 随机乱序数组
  647. * @param array
  648. * @returns
  649. */
  650. static randomArray(array) {
  651. // 使用 Fisher-Yates Shuffle 算法
  652. for (var i = array.length - 1; i > 0; i--) {
  653. var j = Math.floor(Math.random() * (i + 1)); // 交换元素
  654. [array[i], array[j]] = [array[j], array[i]];
  655. }
  656. return array;
  657. }
  658. /**
  659. * 获得开始和结束两者之间相隔分钟数
  660. *
  661. * @static
  662. * @param {number} start
  663. * @param {number} end
  664. * @memberof utils
  665. */
  666. static getOffsetMimutes(start, end) {
  667. var offSetTime = end - start;
  668. var minute = Math.floor(offSetTime % (1000 * 60 * 60) / (1000 * 60));
  669. return minute;
  670. }
  671. /**
  672. * 获取随机小数
  673. * @param {Number} min 最小值
  674. * @param {Number} max 最大值
  675. * @returns
  676. */
  677. static getRandomFloat(min, max) {
  678. return Math.random() * (max - min) + min;
  679. }
  680. /**
  681. * 返回指定小数位的数值
  682. * @param {number} num
  683. * @param {number} idx
  684. */
  685. static formatNumToFixed(num, idx) {
  686. if (idx === void 0) {
  687. idx = 0;
  688. }
  689. return Number(num.toFixed(idx));
  690. }
  691. /**
  692. * 用于数值到达另外一个目标数值之间进行平滑过渡运动效果
  693. * @param {number} targetValue 目标数值
  694. * @param {number} curValue 当前数值
  695. * @param {number} ratio 过渡比率
  696. * @returns
  697. */
  698. static lerp(targetValue, curValue, ratio) {
  699. if (ratio === void 0) {
  700. ratio = 0.25;
  701. }
  702. var v = curValue;
  703. if (targetValue > curValue) {
  704. v = curValue + (targetValue - curValue) * ratio;
  705. } else if (targetValue < curValue) {
  706. v = curValue - (curValue - targetValue) * ratio;
  707. }
  708. return v;
  709. }
  710. /**
  711. * 数据解密
  712. * @param {String} str
  713. */
  714. static decrypt(b64Data) {
  715. if (b64Data == null || b64Data == undefined) {
  716. return "";
  717. }
  718. var n = 6;
  719. if (b64Data.length % 2 === 0) {
  720. n = 7;
  721. }
  722. var decodeData = '';
  723. for (var idx = 0; idx < b64Data.length - n; idx += 2) {
  724. decodeData += b64Data[idx + 1];
  725. decodeData += b64Data[idx];
  726. }
  727. decodeData += b64Data.slice(b64Data.length - n + 1);
  728. decodeData = this._base64Decode(decodeData);
  729. return decodeData;
  730. }
  731. /**
  732. * 数据加密
  733. * @param {String} str
  734. */
  735. static encrypt(str) {
  736. if (str == null || str == undefined) {
  737. return "";
  738. }
  739. var b64Data = this._base64encode(str);
  740. var n = 6;
  741. if (b64Data.length % 2 === 0) {
  742. n = 7;
  743. }
  744. var encodeData = '';
  745. for (var idx = 0; idx < (b64Data.length - n + 1) / 2; idx++) {
  746. encodeData += b64Data[2 * idx + 1];
  747. encodeData += b64Data[2 * idx];
  748. }
  749. encodeData += b64Data.slice(b64Data.length - n + 1);
  750. return encodeData;
  751. } //public method for encoding
  752. /**
  753. * base64加密
  754. * @param {string}input
  755. * @returns
  756. */
  757. static _base64encode(input) {
  758. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  759. var output = "",
  760. chr1,
  761. chr2,
  762. chr3,
  763. enc1,
  764. enc2,
  765. enc3,
  766. enc4,
  767. i = 0;
  768. input = this._utf8Encode(input);
  769. while (i < input.length) {
  770. chr1 = input.charCodeAt(i++);
  771. chr2 = input.charCodeAt(i++);
  772. chr3 = input.charCodeAt(i++);
  773. enc1 = chr1 >> 2;
  774. enc2 = (chr1 & 3) << 4 | chr2 >> 4;
  775. enc3 = (chr2 & 15) << 2 | chr3 >> 6;
  776. enc4 = chr3 & 63;
  777. if (isNaN(chr2)) {
  778. enc3 = enc4 = 64;
  779. } else if (isNaN(chr3)) {
  780. enc4 = 64;
  781. }
  782. output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
  783. }
  784. return output;
  785. }
  786. /**
  787. * utf-8 加密
  788. * @param string
  789. * @returns
  790. */
  791. static _utf8Encode(string) {
  792. string = string.replace(/\r\n/g, "\n");
  793. var utftext = "";
  794. for (var n = 0; n < string.length; n++) {
  795. var c = string.charCodeAt(n);
  796. if (c < 128) {
  797. utftext += String.fromCharCode(c);
  798. } else if (c > 127 && c < 2048) {
  799. utftext += String.fromCharCode(c >> 6 | 192);
  800. utftext += String.fromCharCode(c & 63 | 128);
  801. } else {
  802. utftext += String.fromCharCode(c >> 12 | 224);
  803. utftext += String.fromCharCode(c >> 6 & 63 | 128);
  804. utftext += String.fromCharCode(c & 63 | 128);
  805. }
  806. }
  807. return utftext;
  808. }
  809. /**
  810. * utf-8解密
  811. * @param utftext
  812. * @returns
  813. */
  814. static _utf8Decode(utftext) {
  815. var string = "";
  816. var i = 0;
  817. var c = 0;
  818. var c1 = 0;
  819. var c2 = 0;
  820. var c3 = 0;
  821. while (i < utftext.length) {
  822. c = utftext.charCodeAt(i);
  823. if (c < 128) {
  824. string += String.fromCharCode(c);
  825. i++;
  826. } else if (c > 191 && c < 224) {
  827. c2 = utftext.charCodeAt(i + 1);
  828. string += String.fromCharCode((c & 31) << 6 | c2 & 63);
  829. i += 2;
  830. } else {
  831. c2 = utftext.charCodeAt(i + 1);
  832. c3 = utftext.charCodeAt(i + 2);
  833. string += String.fromCharCode((c & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
  834. i += 3;
  835. }
  836. }
  837. return string;
  838. }
  839. /**
  840. * base64解密
  841. * @param {string}input 解密字符串
  842. * @returns
  843. */
  844. static _base64Decode(input) {
  845. var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  846. var output = "";
  847. var chr1;
  848. var chr2;
  849. var chr3;
  850. var enc1;
  851. var enc2;
  852. var enc3;
  853. var enc4;
  854. var i = 0;
  855. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  856. while (i < input.length) {
  857. enc1 = keyStr.indexOf(input.charAt(i++));
  858. enc2 = keyStr.indexOf(input.charAt(i++));
  859. enc3 = keyStr.indexOf(input.charAt(i++));
  860. enc4 = keyStr.indexOf(input.charAt(i++));
  861. chr1 = enc1 << 2 | enc2 >> 4;
  862. chr2 = (enc2 & 15) << 4 | enc3 >> 2;
  863. chr3 = (enc3 & 3) << 6 | enc4;
  864. output = output + String.fromCharCode(chr1);
  865. if (enc3 != 64) {
  866. output = output + String.fromCharCode(chr2);
  867. }
  868. if (enc4 != 64) {
  869. output = output + String.fromCharCode(chr3);
  870. }
  871. }
  872. output = this._utf8Decode(output);
  873. return output;
  874. }
  875. /**
  876. * 页面渐隐渐显动画
  877. * @param n 节点
  878. * @param isApper 是否是出现
  879. * @param restore 是否恢复255显示的状态
  880. * @param cb 执行完回调
  881. */
  882. static pageAnim(n, isApper, cb) {
  883. if (isApper === void 0) {
  884. isApper = true;
  885. }
  886. var uiop = n.getComponent(UIOpacity);
  887. if (!n || !uiop) {
  888. cb == null || cb();
  889. } else {
  890. uiop.opacity = isApper ? 25 : 255;
  891. var toOpacity = isApper ? 255 : 25;
  892. tween(uiop).to(0.4, {
  893. opacity: toOpacity
  894. }).call(function () {
  895. cb == null || cb();
  896. }.bind(this)).start();
  897. }
  898. }
  899. /**
  900. * 将数组(array)拆分成多个 size 长度的区块,并将这些区块组成一个新数组
  901. * @param {Array}array
  902. * @param {number}size
  903. * @returns
  904. */
  905. static chunk(array, size) {
  906. var length = array === null ? 0 : array.length;
  907. if (!length || size < 1) {
  908. return [];
  909. }
  910. var result = [];
  911. while (array.length > size) {
  912. result.push(array.slice(0, size));
  913. array = array.slice(size);
  914. }
  915. result.push(array);
  916. return result;
  917. }
  918. /**
  919. * 一个字符串首字母大写
  920. */
  921. static upperCase(str) {
  922. if (this.isNull(str)) return "";
  923. return str.replace(/^\w/, c => c.toUpperCase());
  924. }
  925. /**
  926. * 查询一个节点下的子节点
  927. */
  928. static findName(root, name) {
  929. var child;
  930. if (name.indexOf("/") != -1) {
  931. child = find(name, root);
  932. } else {
  933. if (!root) {
  934. root = director.getScene();
  935. }
  936. if (root.name === name) {
  937. child = root;
  938. } else {
  939. child = this.findChild(name, root);
  940. }
  941. }
  942. if (child) {
  943. return child;
  944. } else {
  945. console.log("没有找到指定的Node, node name ==", name);
  946. return null;
  947. }
  948. }
  949. static findChild(name, parent) {
  950. var child = parent.getChildByName(name);
  951. if (child) {
  952. return child;
  953. } else {
  954. var children = parent.children;
  955. for (var i = 0; i < children.length; i++) {
  956. child = this.findChild(name, children[i]);
  957. if (child) {
  958. return child;
  959. }
  960. }
  961. }
  962. return null;
  963. }
  964. /**
  965. * 处理万为单位
  966. * @param num 数值
  967. * @param point 保留小数点
  968. * @param s 是否去掉无用的0
  969. * @returns
  970. */
  971. static numUnit(num, point, f) {
  972. if (point === void 0) {
  973. point = 0;
  974. }
  975. if (f === void 0) {
  976. f = true;
  977. }
  978. var n = num;
  979. var unit = 10000;
  980. if (n > unit) {
  981. if (point == 0) {
  982. n = Math.ceil(n / unit);
  983. return n.toString() + "万";
  984. } else {
  985. var s = (n / unit).toFixed(point);
  986. if (f) {
  987. return this.removeZeros(s) + "万";
  988. } else {
  989. return s + "万";
  990. }
  991. }
  992. } else {
  993. return Math.ceil(num).toString();
  994. }
  995. }
  996. /**
  997. * 格式化数字:
  998. * * 如果小数部分全是 0(如 38.0 或 38.00),去掉小数部分,返回整数。
  999. * 如果是小数(如 38.1 或 38.01),保留两位小数。
  1000. * @param num 输入的数字
  1001. * @returns 格式化后的数字
  1002. */
  1003. static formatNumber(num) {
  1004. // 如果 num 是 undefined 或 null,返回 0 或空字符串
  1005. if (num == undefined || num == null) return 0; //将数字转换为字符串
  1006. var numStr = num.toString(); //判断小数部分是否全是 0 如果小数部分全是 0,去掉小数部分并返回整数
  1007. if (numStr.includes('.') && /\.0+$/.test(numStr)) {
  1008. return parseInt(numStr, 10);
  1009. } else {
  1010. //否则保留两位小数
  1011. var fixedNum = num.toFixed(2); //如果小数部分全是 0,去掉小数部分
  1012. if (fixedNum.endsWith(".00")) {
  1013. return parseInt(fixedNum, 10);
  1014. }
  1015. return parseFloat(fixedNum);
  1016. }
  1017. }
  1018. /**
  1019. * 去掉小数点后无用的0
  1020. * @param numberString 字符串呢
  1021. * @returns
  1022. */
  1023. static removeZeros(numberString) {
  1024. var trimmedString = numberString.trim(); // 去除首尾空格
  1025. var decimalIndex = trimmedString.indexOf('.');
  1026. if (decimalIndex !== -1) {
  1027. var endIndex = trimmedString.length - 1;
  1028. while (trimmedString[endIndex] === '0') {
  1029. endIndex--;
  1030. }
  1031. if (trimmedString[endIndex] === '.') {
  1032. endIndex--; // 如果小数点后面全是零,也去掉小数点
  1033. }
  1034. return trimmedString.slice(0, endIndex + 1);
  1035. }
  1036. return trimmedString;
  1037. }
  1038. /**
  1039. * 数组移除某一个元素
  1040. */
  1041. static remove(arr, param) {
  1042. var index = arr.indexOf(param);
  1043. if (index > -1) {
  1044. arr.splice(index, 1);
  1045. }
  1046. }
  1047. /**
  1048. * 16进制的颜色
  1049. * @param hexColor
  1050. * @returns
  1051. */
  1052. static hexColor(hexColor) {
  1053. var hex = hexColor.replace(/^#?/, "0x");
  1054. var c = parseInt(hex);
  1055. var r = c >> 16;
  1056. var g = (65280 & c) >> 8;
  1057. var b = 255 & c;
  1058. return new Color(r, g, b, 255);
  1059. }
  1060. /**
  1061. * 检查是否有铭感词
  1062. * @param str 文字
  1063. * @returns 返回是否有铭感词
  1064. */
  1065. static filtion(str) {
  1066. return (_crd && sensitiveArray === void 0 ? (_reportPossibleCrUseOfsensitiveArray({
  1067. error: Error()
  1068. }), sensitiveArray) : sensitiveArray).some(word => {
  1069. //忽略大小写匹配
  1070. var lowerCaseStr = str.toLowerCase();
  1071. var lowerCaseWord = word.toLowerCase();
  1072. return lowerCaseStr.includes(lowerCaseWord);
  1073. });
  1074. }
  1075. /**
  1076. * 计算两点间的距离
  1077. */
  1078. static pDistance(localPos, tarPos) {
  1079. var dx = localPos.x - tarPos.x;
  1080. var dy = localPos.y - tarPos.y;
  1081. var dis = Math.sqrt(dx * dx + dy * dy);
  1082. return dis;
  1083. }
  1084. /**
  1085. * 计算两点之间的绝对距离
  1086. */
  1087. static pAbsDistance(a, b) {
  1088. var p = Math.abs(a.x - b.x);
  1089. var k = Math.abs(a.y - b.y);
  1090. return p + k;
  1091. }
  1092. /**
  1093. * 角度转向量
  1094. * @param angle
  1095. * @returns
  1096. */
  1097. static angle_to_vector(angle) {
  1098. // tan = sin / cos 将传入的角度转为弧度
  1099. var radian = this.angle_to_radian(angle); // 算出cos,sin和tan
  1100. var cos = Math.cos(radian); // 邻边 / 斜边
  1101. var sin = Math.sin(radian); // 对边 / 斜边
  1102. var tan = sin / cos; // 对边 / 邻边
  1103. //结合在一起并归一化
  1104. var vec = new Vec2(cos, sin).normalize(); //返回向量
  1105. return vec;
  1106. }
  1107. /**
  1108. * 向量转角度
  1109. * @param vector
  1110. * @returns
  1111. */
  1112. static vector_to_angle(vector) {
  1113. //将传入的向量归一化
  1114. var dir = vector.normalize(); //计算出目标角度的弧度
  1115. var radian = dir.signAngle(new Vec2(1, 0)); //把弧度计算成角度
  1116. var angle = -this.radian_to_angle(radian); //返回角度
  1117. return angle;
  1118. }
  1119. /**
  1120. * 角度转弧度
  1121. * @param angle
  1122. * @returns
  1123. */
  1124. static angle_to_radian(angle) {
  1125. //角度转弧度公式 π / 180 * 角度 计算出弧度
  1126. var radian = Math.PI / 180 * angle; //返回弧度
  1127. return radian;
  1128. }
  1129. /**
  1130. * 弧度转角度
  1131. * @param radian
  1132. * @returns
  1133. */
  1134. static radian_to_angle(radian) {
  1135. //弧度转角度公式 180 / π * 弧度 计算出角度
  1136. var angle = 180 / Math.PI * radian; //返回角度
  1137. return angle;
  1138. }
  1139. /**
  1140. * 计算弧度
  1141. * @param start
  1142. * @param end
  1143. */
  1144. static getAngle(start, end) {
  1145. //两点的x、y值
  1146. var x = end.x - start.x;
  1147. var y = end.y - start.y;
  1148. var hypotenuse = Math.sqrt(x * x + y * y); //斜边长度
  1149. var cos = x / hypotenuse;
  1150. var radian = Math.acos(cos); //求出弧度
  1151. var angle = 180 / (Math.PI / radian); //用弧度算出角度
  1152. if (y < 0) {
  1153. angle = 0 - angle;
  1154. } else if (y == 0 && x < 0) {
  1155. angle = 180;
  1156. }
  1157. return angle;
  1158. }
  1159. /**
  1160. * 扣血转化成字符串
  1161. * @param number
  1162. * @returns
  1163. */
  1164. static numberToString(number) {
  1165. var str = '';
  1166. var data = [{
  1167. minnum: 1000000000,
  1168. maxnum: 9999999999,
  1169. toStr: 'o'
  1170. }, {
  1171. minnum: 100000000,
  1172. maxnum: 999999999,
  1173. toStr: 'p'
  1174. }, {
  1175. minnum: 10000000,
  1176. maxnum: 99999999,
  1177. toStr: 't'
  1178. }, {
  1179. minnum: 1000000,
  1180. maxnum: 9999999,
  1181. toStr: 'g'
  1182. }, {
  1183. minnum: 100000,
  1184. maxnum: 999999,
  1185. toStr: 'm'
  1186. }, {
  1187. minnum: 10000,
  1188. maxnum: 99999,
  1189. toStr: 'b'
  1190. }, {
  1191. minnum: 1000,
  1192. maxnum: 9999,
  1193. toStr: 'K'
  1194. }];
  1195. for (var i = 0; i < data.length; i++) {
  1196. if (number >= data[i].minnum && number <= data[i].maxnum) {
  1197. number /= data[i].minnum;
  1198. var m = number.toFixed(1);
  1199. str = m + data[i].toStr;
  1200. return str;
  1201. }
  1202. }
  1203. return number.toFixed(0);
  1204. }
  1205. /**
  1206. * 将某个节点下的坐标转移到另外一个节点
  1207. * @param fromNode 坐标所在的节点
  1208. * @param toNode 目标节点
  1209. * @returns 转换后的坐标值
  1210. */
  1211. static convertPosition(fromNode, toNode) {
  1212. var pos = fromNode.position.clone(); // 将 pos 转为世界坐标系下的坐标
  1213. var worldPos = fromNode.parent.getComponent(UITransform).convertToWorldSpaceAR(pos); // 将世界坐标系下的坐标转为目标节点的局部坐标系下的坐标
  1214. var localPos = toNode.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
  1215. return localPos;
  1216. }
  1217. /**
  1218. * 以敌人的中心点 攻击范围为半径 产生随机坐标
  1219. * @param center 中心点
  1220. * @param radius 半径
  1221. * @returns
  1222. */
  1223. static randomPointGenerator(center, radius) {
  1224. //随机角度
  1225. var angle = Math.random() * Math.PI * 2; //随机距离
  1226. var distance = Math.sqrt(Math.random()) * radius; //根据极坐标转换成笛卡尔坐标
  1227. var x = center.x + distance * Math.cos(angle);
  1228. var y = center.y + distance * Math.sin(angle);
  1229. return new Vec3(x, y, 1);
  1230. }
  1231. /**
  1232. * 将某个节点上的坐标转移到另外一个节点
  1233. * @param fromNode 坐标所在的节点
  1234. * @param toNode 目标节点
  1235. * @returns 转换后的坐标值
  1236. */
  1237. static convertPositionPos(fromNode, pos, toNode) {
  1238. var nPos = pos.clone(); // 将 pos 转为世界坐标系下的坐标
  1239. var worldPos = fromNode.parent.getComponent(UITransform).convertToWorldSpaceAR(nPos); // 将世界坐标系下的坐标转为目标节点的局部坐标系下的坐标
  1240. var localPos = toNode.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
  1241. return localPos;
  1242. }
  1243. /**
  1244. * 获取屏幕中心对应的3D世界坐标
  1245. * @param camera 摄像机
  1246. * @param groundY 地面高度
  1247. * @returns
  1248. */
  1249. static getScreenCenterWorldPos(camera, groundY) {
  1250. if (groundY === void 0) {
  1251. groundY = 0;
  1252. }
  1253. if (!camera) return Vec3.ZERO; //获取屏幕中心坐标
  1254. var screenSize = view.getVisibleSize();
  1255. var centerX = screenSize.width / 2;
  1256. var centerY = screenSize.height / 2; //生成从屏幕中心发出的射线
  1257. var ray = camera.screenPointToRay(centerX, centerY); //计算射线与特定平面的交点(假设地面Y=0)
  1258. var distance = (groundY - ray.o.y) / ray.d.y; // 4. 返回交点坐标
  1259. return new Vec3(ray.o.x + ray.d.x * distance, ray.o.y + ray.d.y * distance, ray.o.z + ray.d.z * distance);
  1260. }
  1261. /**
  1262. * 让相机平滑看向目标节点
  1263. * @param selfNode 设置方向的节点
  1264. * @param targetNode 目标节点
  1265. * @param duration 平滑过渡时间(秒),默认0.3秒
  1266. */
  1267. static lookAtNode(selfNode, targetNode, duration) {
  1268. if (duration === void 0) {
  1269. duration = 0.3;
  1270. }
  1271. if (!selfNode || !targetNode) return; //计算水平方向(忽略Y轴差异)
  1272. var targetPos = targetNode.worldPosition;
  1273. var selfPos = selfNode.worldPosition;
  1274. var direction = new Vec3();
  1275. Vec3.subtract(direction, targetPos, selfPos); //关键修复:将Y轴归零计算水平方向
  1276. var horizontalDir = new Vec3(direction.x, 0, direction.z).normalize(); //计算垂直角度(仅Y轴差异)
  1277. var distance = Vec3.distance(targetPos, selfPos);
  1278. var heightDiff = targetPos.y - selfPos.y;
  1279. var verticalAngle = math.toRadian(math.clamp(Math.atan2(heightDiff, Math.sqrt(direction.x * direction.x + direction.z * direction.z)) * 180 / Math.PI, -89, 89 // 限制在±89度内防止万向节锁
  1280. )); //构建最终旋转(先水平后垂直)
  1281. var targetRotation = new Quat();
  1282. Quat.fromViewUp(targetRotation, horizontalDir, Vec3.UP); //添加垂直旋转
  1283. var verticalRot = new Quat();
  1284. Quat.fromEuler(verticalRot, verticalAngle, 0, 0);
  1285. Quat.multiply(targetRotation, targetRotation, verticalRot); //应用旋转
  1286. if (duration <= 0) {
  1287. selfNode.setRotation(targetRotation);
  1288. } else {
  1289. var startRotation = selfNode.rotation.clone();
  1290. tween(selfNode).to(duration, {
  1291. rotation: targetRotation
  1292. }, {
  1293. onUpdate: (_, ratio) => {
  1294. var currentRot = new Quat();
  1295. Quat.slerp(currentRot, startRotation, targetRotation, ratio);
  1296. selfNode.setRotation(currentRot);
  1297. }
  1298. }).start();
  1299. }
  1300. }
  1301. /**
  1302. * 根据A,B两个坐标点 和抛物线的弧度 来计算中心点坐标
  1303. */
  1304. static calculateParabolaCenter(start, end) {
  1305. // 计算两点之间的水平距离
  1306. var deltaX = end.x - start.x; // 将控制点的 x 坐标设置为两点的中点
  1307. var controlX = (start.x + end.x) / 2; // 计算抛物线的最高点,使其位于两点之间的中间位置 可以根据需要调整最高点的位置
  1308. var highestY = Math.max(start.y, end.y) + Math.abs(deltaX) / 4; // 计算控制点的 y 坐标
  1309. var controlY = highestY; //返回抛物线的中心坐标点
  1310. return new Vec3(controlX, controlY);
  1311. }
  1312. /**
  1313. * 在UI坐标系内生成安全的随机点
  1314. * @param uiParent 父节点(UITransform)
  1315. * @param center 中心点(Vec3) - 基于父节点的本地坐标
  1316. * @param radius 半径(Number) - 单位为像素
  1317. */
  1318. static randomUIPointGenerator(uiParent, center, radius) {
  1319. // 将像素半径转换为世界坐标比例
  1320. var uiSize = uiParent.getComponent(UITransform).contentSize;
  1321. var maxRadius = Math.min(uiSize.width / 2 - Math.abs(center.x), uiSize.height / 2 - Math.abs(center.y));
  1322. var safeRadius = Math.min(radius, maxRadius); //生成随机角度和距离(距离使用平方根使分布均匀)
  1323. var angle = Math.random() * Math.PI * 2;
  1324. var distance = Math.sqrt(Math.random()) * safeRadius; //转换为本地坐标
  1325. return new Vec3(center.x + distance * Math.cos(angle), center.y + distance * Math.sin(angle), 0 // UI节点z轴设为0
  1326. );
  1327. }
  1328. /**
  1329. * 生成一个随机颜色值的函数
  1330. */
  1331. static getRandomColor() {
  1332. var r = Math.floor(Math.random() * 256);
  1333. var g = Math.floor(Math.random() * 256);
  1334. var b = Math.floor(Math.random() * 256);
  1335. return new Color(r, g, b);
  1336. }
  1337. }) || _class));
  1338. /**
  1339. * //摄像机正前方是跟随枪
  1340. const targetPos = Game.I.player.node.worldPosition;
  1341. const playerRotation = Game.I.player.node.worldRotation;
  1342. const offset = new Vec3(0, 2, -8); // 上方2单位,后方5单位
  1343. // 计算世界空间偏移
  1344. const worldOffset = Vec3.transformQuat(new Vec3(),
  1345. offset,
  1346. playerRotation
  1347. );
  1348. Game.I.camera.node.worldPosition = Vec3.add(new Vec3(), targetPos, worldOffset);
  1349. Game.I.camera.node.lookAt(targetPos);
  1350. let crossPos: Vec3 = Utils.getScreenCenterWorldPos(Game.I.camera);
  1351. const direction = Vec3.subtract(new Vec3(), crossPos, gun.node.worldPosition);
  1352. direction.normalize();
  1353. Game.I.camera.node.forward = direction;
  1354. */
  1355. _cclegacy._RF.pop();
  1356. _crd = false;
  1357. }
  1358. };
  1359. });
  1360. //# sourceMappingURL=59c9a449918b535a4c703ec0f09f091f198a0d28.js.map