Tools.ts 19 KB

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