Tools.ts 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. import Global, {ExportData} from "./Global";
  2. import LoadMgr from "./manage/LoadMgr";
  3. import CacheMgr from "./manage/CacheMgr";
  4. import GameLogMgr from "./manage/GameLogMgr";
  5. import JiuWuSDK from "../SDK/JiuWuSDK";
  6. import Game from "../Scene/Game";
  7. import PanelMgr, {Layer} from "./manage/PanelMgr";
  8. import ShortageView from "../Moudle/View/ShortageView";
  9. import isNumber = cc.js.isNumber;
  10. import QgNative from "./manage/Api/QgNative";
  11. import LogMgr from "./LogMgr";
  12. import NativeView from "../Moudle/View/NativeView";
  13. import QgRewardedAd from "./manage/Api/QgRewardedAd";
  14. import QgIntersAd from "./manage/Api/QgIntersAd";
  15. import AudioMgr from "./manage/AudioMgr";
  16. export default class Tools {
  17. public static subStr(str, n) {
  18. let r = /[^\x00-\xff]/g;
  19. if (str.replace(r, "mm").length <= n) {
  20. return str;
  21. }
  22. let m = Math.floor(n / 2);
  23. for (let i = m; i < str.length; i++) {
  24. if (str.substr(0, i).replace(r, "mm").length >= n) {
  25. return str.substr(0, i) + "...";
  26. }
  27. }
  28. return str;
  29. }
  30. /**
  31. * 短震动
  32. * light 轻震动
  33. * medium 中震动
  34. * heavy 重震动
  35. */
  36. public static vibrateShort(type: string = 'heavy', number: number = 10) {
  37. // @ts-ignore
  38. if (!window.qg) {
  39. return
  40. }
  41. for (let index = 0; index < number; index++) {
  42. // @ts-ignore
  43. qg.vibrateShort();
  44. }
  45. }
  46. /**
  47. * 短震动
  48. */
  49. public static vibrateLong() {
  50. // @ts-ignore
  51. if (!window.qg) {
  52. return
  53. }
  54. // @ts-ignore
  55. qg.vibrateLong();
  56. }
  57. //判断一个值是否在一个数组中
  58. public static JudgeValueInArr(value: any, arr: Array<any>) {
  59. let flag = false
  60. for (let i = 0; i < arr.length; i++) {
  61. if (arr[i] === value) {
  62. flag = true
  63. break
  64. }
  65. }
  66. return flag
  67. }
  68. /**
  69. * 对象深拷贝
  70. * @param obj
  71. */
  72. public static deepClone(obj) {
  73. try {
  74. return JSON.parse(JSON.stringify(obj));
  75. } catch (e) {
  76. return obj;
  77. }
  78. }
  79. /**
  80. * 获取整数随机值
  81. * @param maxValue
  82. * @return [0, max)
  83. */
  84. public static getRandomMax(maxValue: number) {
  85. return Math.floor(Math.random() * maxValue)
  86. }
  87. /**
  88. * 获取数组随机值
  89. * @param array
  90. */
  91. public static getRandomByArray(array: any) {
  92. try {
  93. return array[this.getRandomMax(array.length)];
  94. } catch (e) {
  95. GameLogMgr.error('获取数组随机值异常', e);
  96. }
  97. return {};
  98. }
  99. /**
  100. * 获取整数随机值
  101. * @param minValue
  102. * @param maxValue
  103. * @return [min, max)
  104. */
  105. public static getRandom(minValue: number, maxValue: number): number {
  106. return Math.floor(Math.random() * (maxValue - minValue) + minValue);
  107. }
  108. /**
  109. * 获取随机值
  110. * @param minValue
  111. * @param maxValue
  112. * @return (min, max]
  113. */
  114. public static getRealRandom(minValue: number, maxValue: number): number {
  115. return Math.random() * (maxValue - minValue) + minValue;
  116. }
  117. public static sort(arr: any[], begin: number = 0, end: number = arr.length): Array<number> {
  118. if (end <= begin)
  119. return arr;
  120. let i = begin;
  121. let j = end;
  122. let key = arr[begin].sort;
  123. while (true) {
  124. while (true) {
  125. if (i == j) break;
  126. if (arr[j].sort < key) {
  127. let temp = arr[j];
  128. arr[j] = arr[i];
  129. arr[i] = temp;
  130. break;
  131. }
  132. j--;
  133. }
  134. while (true) {
  135. if (i == j) break;
  136. if (arr[i].sort > key) {
  137. let temp = arr[i];
  138. arr[i] = arr[j];
  139. arr[j] = temp;
  140. break;
  141. }
  142. i++;
  143. }
  144. if (i == j)
  145. break;
  146. }
  147. if (end - j > 1) {
  148. arr = Tools.sort(arr, j + 1, end);
  149. }
  150. if (i - begin > 1) {
  151. arr = Tools.sort(arr, begin, i);
  152. }
  153. return arr;
  154. }
  155. /**
  156. * 快速排序导出信息:
  157. * @param arr 需要进行快速排序的数组
  158. * @returns {*[]|*}
  159. */
  160. public static quickExportSort(arr: ExportData[]) {
  161. arr.sort(() => {
  162. return 0.5 - Math.random()
  163. })
  164. if (CacheMgr.earlyExportTripPart.length > 0) {
  165. let arr2 = []
  166. for (let i = arr.length - 1; i >= 0; i--) {
  167. if (this.judgeValueInArr(arr[i].appId, CacheMgr.earlyExportTripPart)) {
  168. arr2.push(Tools.deepClone(arr[i]))
  169. arr.splice(i, 1)
  170. }
  171. }
  172. for (let i = 0; i < arr2.length; i++) {
  173. arr.push(arr2[i])
  174. }
  175. }
  176. return arr
  177. }
  178. /**
  179. * 改变节点位置的 y 为 banner 位置的 y (骗点用)
  180. * @param node
  181. */
  182. public static changeNodePosition(node: cc.Node) {
  183. let banner = Game.Ins.banner;
  184. node.y = banner.y + banner.height / 2;
  185. }
  186. /**
  187. * 调整按钮位置到 banner上方
  188. * @param button
  189. */
  190. public static setExportPos(button: cc.Node) {
  191. let banner = Game.Ins.banner;
  192. this.changeNodePosition(button);
  193. button.y = button.y + banner.height / 2 + button.height / 2;
  194. }
  195. /**
  196. * 骗点结束移动 按钮
  197. * @param time
  198. * @param button
  199. */
  200. public static setExportPos_Animation(time: number, button: cc.Node) {
  201. let banner = Game.Ins.banner
  202. this.changeNodePosition(button);
  203. cc.tween(button)
  204. .to(time, {y: button.y + banner.height / 2 + button.height / 2}, {easing: "smooth"})
  205. .start();
  206. }
  207. /**
  208. * 判断百分比
  209. * @param per
  210. */
  211. public static checkPer(per: number) {
  212. if (!per) {
  213. return false;
  214. }
  215. return Tools.getRandomMax(100) <= per;
  216. }
  217. /**
  218. * 游戏链接后台,资源加载, 初始化 gameBox
  219. */
  220. public static model_initModel(f: Function): number {
  221. let functions: Function[] = [
  222. () => {
  223. let names = ["sub","homeView","gameView"]
  224. LoadMgr.loadBundle(names).then(() => {
  225. f()
  226. })
  227. },
  228. () => {
  229. f();
  230. },
  231. ]
  232. for (let i = 0; i < functions.length; i++) {
  233. functions[i]();
  234. }
  235. return functions.length;
  236. }
  237. /**
  238. * 播放视频, resolve 返回 true 为获得奖励, false 为未获得奖励
  239. */
  240. public static handleVideo() {
  241. return new Promise((resolve, reject) => {
  242. if (!Global.isVivo) {
  243. resolve(true);
  244. return
  245. }
  246. AudioMgr.backMusic(false) ;
  247. QgRewardedAd.showRewardedVideo().then((res) => {
  248. let boolean : boolean = res == 1 ;
  249. AudioMgr.backMusic() ;
  250. resolve(boolean);
  251. })
  252. })
  253. }
  254. /**
  255. * 打开或关闭 碰撞系统功能
  256. * @param isOpen 碰撞系统
  257. * @param draw debug 绘制
  258. * @param bounding 包围盒
  259. */
  260. public static getCollision(isOpen: boolean = true, draw: boolean = false, bounding: boolean = false) {
  261. let Manager = cc.director.getCollisionManager();
  262. Manager.enabled = isOpen;
  263. Manager.enabledDebugDraw = draw;
  264. Manager.enabledDrawBoundingBox = bounding;
  265. }
  266. /**
  267. * 打开或关闭 物理系统
  268. * @param isOpen
  269. * @param draw
  270. */
  271. public static getPhysics(isOpen: boolean = true, draw: boolean = false) {
  272. let Manager = cc.director.getPhysicsManager();
  273. Manager.enabled = true;
  274. if (draw) {
  275. cc.director.getPhysicsManager().debugDrawFlags =
  276. cc.PhysicsManager.DrawBits.e_aabbBit
  277. |
  278. cc.PhysicsManager.DrawBits.e_jointBit
  279. |
  280. cc.PhysicsManager.DrawBits.e_shapeBit
  281. ;
  282. }
  283. }
  284. /**
  285. * 注册一组 touch 事件
  286. * @param node
  287. * @param start
  288. * @param move
  289. * @param end
  290. * @param cancel
  291. * @param target
  292. * @param bool
  293. */
  294. public static onTouchAll(node: cc.Node, start: Function, move: Function, end: Function, cancel: Function, target: any, bool: boolean = true) {
  295. if (node) {
  296. if (bool) {
  297. node.on(cc.Node.EventType.TOUCH_START, start, target);
  298. node.on(cc.Node.EventType.TOUCH_MOVE, move, target);
  299. node.on(cc.Node.EventType.TOUCH_END, end, target);
  300. node.on(cc.Node.EventType.TOUCH_CANCEL, cancel, target);
  301. } else {
  302. node.off(cc.Node.EventType.TOUCH_START, start, target);
  303. node.off(cc.Node.EventType.TOUCH_MOVE, move, target);
  304. node.off(cc.Node.EventType.TOUCH_END, end, target);
  305. node.off(cc.Node.EventType.TOUCH_CANCEL, cancel, target);
  306. }
  307. }
  308. }
  309. /**
  310. * 获取节点所在父节点的下标
  311. * @param node
  312. */
  313. public static getChildrenIndex(node: cc.Node): number {
  314. let parent = node.parent;
  315. for (let i = 0; i < parent.children.length; i++) {
  316. let value = parent.children[i];
  317. if (node === value) {
  318. return i;
  319. }
  320. }
  321. }
  322. /**
  323. * 该位置是否在节点中
  324. * @param point 位置
  325. * @param node 节点
  326. */
  327. public static getPointInNode(point: cc.Vec2, node: cc.Node): boolean {
  328. return node.getBoundingBoxToWorld().contains(point);
  329. }
  330. /**
  331. * 获取比较奇怪的时间字符串 (特定的一天) 20210203
  332. */
  333. public static date_getTimeNum(date: Date) {
  334. return date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate()
  335. }
  336. /**
  337. * 获取两个时间的时间差
  338. * @param start1 比较靠后的时间
  339. * @param start2 比较靠前的时间
  340. * @param type 获取的时间差类型 0 day 1 hour 2 minuter 3 second
  341. */
  342. public static date_getTimeDifference(start1: Date | number, start2: Date | number, type: number): any {
  343. if (isNumber(start1)) {
  344. start1 = new Date(start1)
  345. }
  346. if (isNumber(start2)) {
  347. start2 = new Date(start2)
  348. }
  349. if (start1 instanceof Date && start2 instanceof Date) {
  350. let distance = start1.getTime() - start2.getTime(); //时间差秒
  351. switch (type) {
  352. case 0:
  353. return {
  354. distance: Math.floor(distance / (24 * 60 * 60 * 1000)),
  355. distance_real: distance,
  356. }
  357. case 1 :
  358. return {
  359. distance: Math.floor(distance / (60 * 60 * 1000)),
  360. distance_real: distance,
  361. }
  362. case 2 :
  363. return {
  364. distance: Math.floor(distance / (60 * 1000)),
  365. distance_real: distance,
  366. }
  367. case 3 :
  368. return {
  369. distance: Math.floor(distance / (1000)),
  370. distance_real: distance,
  371. }
  372. }
  373. }
  374. }
  375. /**
  376. * 获取当前主机地址
  377. */
  378. public static getHost(): string {
  379. return JiuWuSDK.url.host;
  380. }
  381. /**
  382. * 根据一个矩形 ,创建一个节点
  383. */
  384. public static getNodeForRect(rect: cc.Rect): cc.Node {
  385. let node = new cc.Node();
  386. node.width = rect.width;
  387. node.height = rect.height;
  388. node.setPosition(cc.v3(rect.center));
  389. return node;
  390. }
  391. /**
  392. * 获取一个节点四个点的位置 (未经旋转 这种操作)
  393. * @param node
  394. */
  395. //获取一个节点四个点的位置 (未经旋转 这种操作)
  396. public static getNodeFourPoint(node: cc.Node) {
  397. let anchor = node.getAnchorPoint()
  398. return {
  399. left_down: cc.v2(node.position.x - anchor.x * node.width, node.position.y - anchor.y * node.height),
  400. left_top: cc.v2(node.position.x - anchor.x * node.width, node.position.y + (1 - anchor.y) * node.height),
  401. right_down: cc.v2(node.position.x + (1 - anchor.x) * node.width, node.position.y - anchor.y * node.height),
  402. right_top: cc.v2(node.position.x + (1 - anchor.x) * node.width, node.position.y + (1 - anchor.y) * node.height)
  403. }
  404. }
  405. //判断一个值是否在一个数组中
  406. public static judgeValueInArr(value: any, arr: Array<any>) {
  407. let flag = false
  408. for (let i = 0; i < arr.length; i++) {
  409. if (arr[i] === value) {
  410. flag = true
  411. break
  412. }
  413. }
  414. return flag
  415. }
  416. //判断两个数组是否相交
  417. public static judgeArraySame(arr1: number[], arr2: number[]) {
  418. let flag = false
  419. for (let i = 0; i < arr1.length; i++) {
  420. for (let j = 0; j < arr2.length; j++) {
  421. if (arr1[i] == arr2[j]) {
  422. flag = true
  423. return flag
  424. }
  425. }
  426. }
  427. return flag
  428. }
  429. //banner根据节点适配
  430. public static getRealSize(node: cc.Node, resize_width = null, resize_height = null): {
  431. width: number,
  432. height: number,
  433. left: number,
  434. top: number
  435. } {
  436. //获取屏幕设计尺寸
  437. let canvas = node.parent
  438. let size = canvas.getContentSize()
  439. let data = Tools.getNodeFourPoint(canvas)
  440. let pc = data.left_top.sub(cc.v2(Tools.getNodeFourPoint(node).left_top))
  441. let screen = cc.view.getFrameSize();
  442. let scaleX = screen.width / size.width
  443. let scaleY = screen.height / size.height
  444. if (resize_width && resize_height) {
  445. node.width = resize_width / scaleX
  446. node.height = resize_height / scaleY
  447. }
  448. // console.log("scaleX", scaleX, "scaleY", scaleY)
  449. return {
  450. width: node.width * scaleX,
  451. height: node.height * scaleY,
  452. left: -pc.x * scaleX,
  453. top: pc.y * scaleY,
  454. }
  455. }
  456. /**
  457. * 修改体力 , 如果体力不足 ,修改失败的话 ,会自动弹出体力不足框
  458. * @param num 需要改动的体力
  459. * @param callBack
  460. */
  461. public static changeStamina(num: number, callBack?: Function): boolean {
  462. if (CacheMgr.stamina + num < 0) {
  463. PanelMgr.INS.openPanel({
  464. panel: ShortageView,
  465. layer: Layer.gameLayer,
  466. param: {
  467. type: "stamina",
  468. callBack: callBack,
  469. price: Math.abs(num),
  470. }
  471. })
  472. return false;
  473. } else {
  474. if (callBack) {
  475. callBack();
  476. }
  477. }
  478. CacheMgr.stamina = CacheMgr.stamina + num;
  479. return true;
  480. }
  481. /**
  482. * 修改金币 , 如果金币不足 ,修改失败的话 ,会自动弹出金币不足框
  483. * @param num
  484. * @param callBack 成功回调 (包括领取金币成功)
  485. */
  486. public static changeGold(num: number, callBack?: Function): boolean {
  487. if (CacheMgr.gold + num < 0) {
  488. PanelMgr.INS.openPanel({
  489. panel: ShortageView,
  490. layer: Layer.gameLayer,
  491. param: {
  492. type: "gold",
  493. callBack: callBack,
  494. price: Math.abs(num),
  495. }
  496. })
  497. return false
  498. } else {
  499. if (callBack) {
  500. callBack();
  501. }
  502. }
  503. CacheMgr.gold = CacheMgr.gold + num
  504. return true
  505. }
  506. /**
  507. * 判断体力 , 如果体力不足 ,修改失败的话 ,会自动弹出体力不足框
  508. * @param num 需要改动的体力
  509. * @param callBack
  510. */
  511. public static judgeStamina(num: number, callBack?: Function): boolean {
  512. if (CacheMgr.stamina + num < 0) {
  513. PanelMgr.INS.openPanel({
  514. panel: ShortageView,
  515. layer: Layer.gameLayer,
  516. param: {
  517. type: "stamina",
  518. callBack: callBack,
  519. price: 0,
  520. }
  521. })
  522. return false;
  523. } else {
  524. if (callBack) {
  525. callBack();
  526. }
  527. }
  528. return true;
  529. }
  530. /**
  531. * 判断金币 , 如果金币不足 ,修改失败的话 ,会自动弹出金币不足框
  532. * @param num
  533. * @param callBack 成功回调 (包括领取金币成功)
  534. */
  535. public static judgeGold(num: number, callBack?: Function): boolean {
  536. if (CacheMgr.gold + num < 0) {
  537. PanelMgr.INS.openPanel({
  538. panel: ShortageView,
  539. layer: Layer.gameLayer,
  540. param: {
  541. type: "gold",
  542. callBack: callBack,
  543. price: num,
  544. }
  545. })
  546. return false
  547. } else {
  548. if (callBack) {
  549. callBack();
  550. }
  551. }
  552. return true
  553. }
  554. /**
  555. * 已知圆心,半径,角度,求圆上的点坐标 (坐标需要自己转)
  556. * @param center
  557. * @param r
  558. * @param angle
  559. */
  560. public static getCirclePoint(center: cc.Vec3, r: number, angle: number): cc.Vec3 {
  561. return cc.v3(
  562. center.x + r * Math.cos(angle * 3.14 / 180),
  563. center.y + r * Math.sin(angle * 3.14 / 180)
  564. )
  565. }
  566. public static handlerInters() {
  567. return new Promise((resolve) => {
  568. if (!Global.isVivo) {
  569. resolve(true);
  570. return
  571. }
  572. QgIntersAd.showInters();
  573. resolve(true);
  574. })
  575. }
  576. /**
  577. * 判断原生广告显示
  578. */
  579. public static showNative(type, labelType, time) {
  580. return new Promise((resolve) => {
  581. if (QgNative.nativeMessage == null) {
  582. QgNative.loadNative().then((res) => {
  583. if (res == false) {
  584. LogMgr.error("原生广告拉取失败......")
  585. resolve(false);
  586. return
  587. }
  588. })
  589. }
  590. PanelMgr.INS.openPanel({
  591. panel: NativeView,
  592. layer: Layer.nativeLayer,
  593. param: {
  594. type: type,
  595. labelType: labelType,
  596. time: time
  597. }
  598. })
  599. resolve(true);
  600. })
  601. }
  602. }