cocosUtil.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. import { isValid, Node, Quat, sp, sys, systemEvent, SystemEvent, tween, UIOpacity, UITransform, v3, Vec3, view } from "cc";
  2. import { constants } from "../game/data/constants";
  3. import { resManager } from "../game/manager/resManager";
  4. export const cocosUtil = {
  5. addHand(attachNode: Node, parent: Node, cb?: Function) {
  6. resManager.instance.loadAsset(constants.bundles.common.name, constants.bundles.common.spine.shouzhi, sp.SkeletonData, () => { }, (err, skeletonData) => {
  7. if (err) {
  8. return;
  9. }
  10. let handNode = new Node();
  11. let handSkeleton = handNode.addComponent(sp.Skeleton);
  12. handSkeleton.skeletonData = skeletonData;
  13. handSkeleton.setAnimation(0, "dianji", true);
  14. handSkeleton.premultipliedAlpha = false;
  15. handNode.parent = parent;
  16. let pos = cocosUtil.convertToWorldSpace(attachNode, true);
  17. pos = cocosUtil.convertToNodeSpace(handNode, pos);
  18. handNode.setPosition(pos);
  19. if (cb) {
  20. cb(handNode);
  21. }
  22. });
  23. },
  24. tweenBlink(node: Node, time?: number) {
  25. if (!time) {
  26. time = 0.5;
  27. }
  28. tween(node.getComponent(UIOpacity)).to(time, {
  29. opacity: 0
  30. }).to(time, {
  31. opacity: 255
  32. }).union().repeatForever().start();
  33. },
  34. tweenRotate(node: Node, time?: number) {
  35. if (!time) {
  36. time = 2;
  37. }
  38. let quat = new Quat();
  39. let angle = 360;
  40. Quat.fromEuler(quat, 0, 0, angle);
  41. tween(node).by(time, { rotation: quat }, {
  42. easing: "linear",
  43. onUpdate: (target: Node, ratio: number) => {
  44. let da = angle * ratio;
  45. Quat.fromEuler(quat, 0, 0, da);
  46. target.setRotation(quat);
  47. }
  48. }).repeatForever().start();
  49. },
  50. tweenUpDown(node: Node, dy?: number, time?: number) {
  51. if (!dy) {
  52. dy = 10;
  53. }
  54. if (!time) {
  55. time = 1;
  56. }
  57. let pos1 = node.getPosition();
  58. pos1.y += dy;
  59. let pos2 = node.getPosition();
  60. tween(node).to(time, {
  61. position: pos1
  62. }).to(time, {
  63. position: pos2
  64. }).union().repeatForever().start();
  65. },
  66. tweenFadeOut(node: Node, time?: number, cb?: Function) {
  67. if (!time) {
  68. time = 1.5;
  69. }
  70. tween(node.getComponent(UIOpacity)).to(time, {
  71. opacity: 0
  72. }).call(() => {
  73. if (cb) {
  74. cb();
  75. }
  76. }).start();
  77. },
  78. /**
  79. * 放大缩小呼吸效果
  80. * @param node 节点
  81. * @param time 缩放时长,单位:秒
  82. * @param scale 缩放大小
  83. */
  84. tweenScaleBreath(node: Node, time?: number, scale?: number) {
  85. if (!time) {
  86. time = 0.4;
  87. }
  88. if (!scale) {
  89. scale = 1.2;
  90. }
  91. tween(node).to(
  92. time, {
  93. scale: v3(scale, scale, 1)
  94. }
  95. ).to(
  96. time, {
  97. scale: v3(1, 1, 1)
  98. }
  99. ).union().repeatForever().start();
  100. },
  101. /**
  102. * 间接性晃动效果
  103. * @param node 节点
  104. * @param time 时长,单位:秒
  105. * @param rotation 旋转角度,单位:度数
  106. * @param delayTime 中间暂停时长,单位:秒
  107. */
  108. tweenShake(node: Node, time?: number, rotation?: number, delayTime?: number) {
  109. if (!time) {
  110. time = 0.2;
  111. }
  112. if (!rotation) {
  113. rotation = 6;
  114. }
  115. if (delayTime == undefined) {
  116. delayTime = time * 5;
  117. }
  118. let quat1: Quat = new Quat();
  119. Quat.fromEuler(quat1, 0, 0, rotation);
  120. let quat2: Quat = new Quat();
  121. Quat.fromEuler(quat2, 0, 0, -rotation);
  122. let quat3: Quat = new Quat();
  123. Quat.fromEuler(quat3, 0, 0, 0);
  124. tween(node).to(time, {
  125. rotation: quat1
  126. }).to(time * 2, {
  127. rotation: quat2
  128. }).to(time, {
  129. rotation: quat3
  130. }).delay(delayTime).union().repeatForever().start();
  131. },
  132. /**
  133. * 判断节点是否可用
  134. * @param node 节点对象
  135. */
  136. isNodeValid(node: Node) {
  137. if (!node || !isValid(node)) {
  138. return false;
  139. }
  140. return true;
  141. },
  142. isAndroid() {
  143. return sys.platform === sys.Platform.ANDROID;
  144. },
  145. isDesktopBrowser() {
  146. return sys.platform === sys.Platform.DESKTOP_BROWSER;
  147. },
  148. isIos() {
  149. return sys.platform === sys.Platform.IOS;
  150. },
  151. isWechatGame() {
  152. return sys.platform === sys.Platform.WECHAT_GAME;
  153. },
  154. addKeyDownListener(cb, sender) {
  155. systemEvent.on(SystemEvent.EventType.KEY_DOWN, cb, sender);
  156. },
  157. init() {
  158. // 设计分辨率
  159. this.designSize = view.getDesignResolutionSize();
  160. // 实际屏幕分辨率
  161. this.frameSize = view.getFrameSize();
  162. // 实际屏幕安全区域,{x: 0, y: 0, width: 766.6256157635468, height: 1660}
  163. // 是以左下角为原点,以设计分辨率为单位的,并且是遵循高度为适配原则后的尺寸
  164. this.safeAreaRect = sys.getSafeAreaRect();
  165. // 计算出顶部刘海屏高度
  166. this.safeAreaMarginTop = this.designSize.height - this.safeAreaRect.height;
  167. if (this.safeAreaMarginTop < 0) {
  168. this.safeAreaMarginTop = 0;
  169. }
  170. this.intiScreenAdapterWidthScale();
  171. this.initScreenBgAdapterWidthScale();
  172. },
  173. // UI适配,以高度为适配原则,按照满宽度显示计算,如果宽度不够显示,要乘以这个缩放比例
  174. intiScreenAdapterWidthScale() {
  175. let fh = this.frameSize.height;
  176. let fw = this.frameSize.width;
  177. let scale = fh / this.designSize.height;
  178. let adapterWidth = this.designSize.width * scale;
  179. let retScale = 1;
  180. if (adapterWidth > fw) {
  181. // 屏幕不够显示,有些交互UI会丢失,要进行缩小
  182. retScale = fw / adapterWidth;
  183. }
  184. // if (this.safeAreaMarginTop > 0) {
  185. // // cocos内部以高度为适配策略,但是如果有刘海屏,要额外再缩放一点
  186. // let subScale = this.safeAreaMarginTop / this.designSize.height;
  187. // retScale -= subScale;
  188. // }
  189. this.screenAdapterScale = retScale;
  190. },
  191. getScreenAdapterScale() {
  192. if (!this.screenAdapterScale) {
  193. this.screenAdapterScale = 1;
  194. }
  195. return this.screenAdapterScale;
  196. },
  197. // 背景图适配,跟上面的UI适配,刚好相反,超出的屏幕不管,屏幕没显示满,要放大
  198. initScreenBgAdapterWidthScale() {
  199. let fh = this.frameSize.height;
  200. let fw = this.frameSize.width;
  201. let scale = fh / this.designSize.height;
  202. let adapterWidth = this.designSize.width * scale;
  203. let retScale = 1;
  204. if (adapterWidth < fw) {
  205. // 屏幕没显示满,会有黑边,要进行放大
  206. retScale = fw / adapterWidth;
  207. }
  208. // if (this.safeAreaMarginTop > 0) {
  209. // // 额外增加放大值,使得背景图铺满包括刘海在内的整个屏幕
  210. // let addScale = this.safeAreaMarginTop / this.designSize.height;
  211. // retScale += addScale;
  212. // }
  213. this.screenBgAdapterScale = retScale;
  214. },
  215. getScreenBgAdapterScale() {
  216. if (!this.screenBgAdapterScale) {
  217. this.screenBgAdapterScale = 1;
  218. }
  219. return this.screenBgAdapterScale;
  220. },
  221. /**
  222. * 将node坐标转换为世界坐标
  223. * @param node
  224. * @param isCenter 是否强制是node的中心点坐标
  225. */
  226. convertToWorldSpace(node: Node, isCenter?: boolean) {
  227. let transform = node.parent.getComponent(UITransform);
  228. let pos = node.getPosition();
  229. if (isCenter) {
  230. let tf = node.getComponent(UITransform);
  231. pos.x = pos.x + (0.5 - tf.anchorX) * tf.width;
  232. pos.y = pos.y + (0.5 - tf.anchorY) * tf.height;
  233. }
  234. return transform.convertToWorldSpaceAR(pos);
  235. },
  236. /**
  237. * 获得以node父节点锚点位置为原点的坐标系下的坐标
  238. * @param node 注意,是同坐标下的节点
  239. * @param pos 世界坐标
  240. */
  241. convertToNodeSpace(node: Node, pos: Vec3) {
  242. let transform = node.parent.getComponent(UITransform);
  243. return transform.convertToNodeSpaceAR(pos);
  244. },
  245. setPositionX(node: Node, x: number) {
  246. let pos = node.getPosition();
  247. pos.x = x;
  248. node.setPosition(pos);
  249. },
  250. setPositionY(node: Node, y: number) {
  251. let pos = node.getPosition();
  252. pos.y = y;
  253. node.setPosition(pos);
  254. },
  255. }