UserGuideTS.txt 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849
  1. /**
  2. * The introduction of two main APIs.
  3. *
  4. * @format
  5. */
  6. /*** 两个主要接口说明。*/
  7. /**
  8. * @en
  9. * Shows guides or a single guide.
  10. * @param step Which step to be guided, 1 by default. You may also pass the alias name of the step.
  11. * @param isAuto Is to play the next guide automatically, false by default.
  12. * @param callback Takes a callback function. which will be called the user completes the current guide. Only works when the parameter isAuto is false. Should use this parameter in single step guide type.
  13. *
  14. * @zh
  15. * 显示连续或单步引导。
  16. * @param step 新手引导的第几步,默认是第一步。也可以传入该引导步骤的别名。
  17. * @param isAuto 完成当前引导后是否自动播放下一个引导。
  18. * @param callback 接收一个回调函数,当用户完成当前引导后会执行该回调函数。只有isAuto为false时才有效,适用于单步引导。
  19. */
  20. // showGuide(step:number|string, isAuto:boolean=false, callback: Function=null)
  21. /**
  22. * @en
  23. * Shows the guide by group.
  24. * @param stepArray The guide steps array, [1, 3, 5] means to execute the fist, the third and the fifth guide step. You may also pass an alias array, e.g., ['alias of guide step1', 'alias of guide step 2'];
  25. * @param callback Takes a callback function. which will be called the user completes the current guide.
  26. * @zh
  27. * 按分组显示引导。
  28. * @param stepArray 要执行各个引导步骤,比如传入[1, 3, 5]表示一次执行第一、第三和第五步引导。也可以传入别名数组['第一步引导别名', '第二步引导别名']。
  29. * @param callback 接收一个回调函数,当用户完成当前引导后会执行该回调函数。
  30. */
  31. // showGuideByGroup(stepArray:Array<number|string>, callback: Function=null)
  32. /**
  33. * @en
  34. * Hides all nodes related to user guide.
  35. * @zh
  36. * 隐藏与引导相关的所有节点。
  37. */
  38. // hideGuide()
  39. /*** Other APIs that are used to adjust the user guide. They have to be called before showGuide() or showGuideByGroup(). */
  40. /*** 其他用于调整引导效果的接口,须在showGuide()或showGuideByGroup()方法前调用。*/
  41. /**
  42. * @en
  43. * Sets the mask color, black and half transparent by default.
  44. * @zh
  45. * 设置遮罩层颜色,默认为黑色半透明。
  46. */
  47. // setMaskColor(color: Color)
  48. /**
  49. * @en
  50. * Sets the mask shape, rect by default. Param value can be 'rect', 'ellipse' or 'sprite stencil'.
  51. * @zh
  52. * 设置遮罩挖洞形状,默认为矩形。参数可选值有'rect','ellipse'或者'sprite stencil'。
  53. */
  54. // setMaskShape(shape: string)
  55. /**
  56. * @en
  57. * Sets the line height of guide text, 28 by default.
  58. * @zh
  59. * 设置引导文本行高,默认为40。
  60. */
  61. // setGuideTextLineHeight(lineHeight: number)
  62. /**
  63. * @en
  64. * Sets the font size of guide text, 28 by default.
  65. * @zh
  66. * 设置引导文本字体大小,默认为28。
  67. */
  68. // setGuideTextFontSize(fontSize: number)
  69. /**
  70. * @en
  71. * Sets the system font of guide text.
  72. * @zh
  73. * 设置引导文本的系统字体。
  74. */
  75. // setGuideTextSystemFont(sysFontName: string)
  76. /**
  77. * @en
  78. * Sets the custom font of guide text.
  79. * @param pathInRes The path of the custom font in resources folder. The format should be ttf and the path should end without the extension name .ttf.
  80. * @zh
  81. * @param pathInRes 自定义字体在resources文件夹中的路径,字体格式为ttf,注意路径最后不带后缀名.ttf。
  82. * 设置引导文本自定义字体。
  83. */
  84. // setGuideTextCustomFont(pathInRes: string)
  85. /**
  86. * @en
  87. * Sets the color of guide text, black by default.
  88. * @zh
  89. * 设置引导文本颜色,默认为黑色。
  90. */
  91. // setGuideTextColor(color: Color)
  92. /**
  93. * @en
  94. * Sets the position of guide text.
  95. * @param textPos Where to show the guide text. Choices are Vec3 type of value (position on Canvas), or string type of value: 'follow', 'center' and 'bottom'. 'follow' means showing next to the target node, 'center' means showing in the center of Canvas and 'bottom' means showing at the bottom of Canvas.
  96. * @zh
  97. * 设置引导文本位置。
  98. * @param textPos 要在哪里显示引导文本,可以是Vec3类型的值,即在画布上的具体位置,或者是字符串类型的值'follow'、'center'和'bottom'。'follow'表示显示在目标节点周围,'center'表示显示在画布中间,'bottom'表示显示在画布底部。
  99. */
  100. // setGuideTextPos(textPos: cc.Vec3 | string='follow')
  101. /**
  102. * @en
  103. * Sets the language type of guide text, 'zh' by default, the other value is 'en'.
  104. * @zh
  105. * 设置引导文本语言种类,默认是'zh',其他可选值为'en'。
  106. */
  107. // setGuideTextLang(lang: string='zh')
  108. /**
  109. * @en
  110. * Sets the scale of guide text background node.
  111. * @zh
  112. * 设置引导文本背景缩放值。
  113. */
  114. // setGuideTextBackgroundScale(scaleX: number, scaleY: number)
  115. /**
  116. * @en
  117. * Sets the scale of guide sign node.
  118. * @zh
  119. * 设置引导图片缩放值。
  120. */
  121. // setGuideSignScale(scaleX: number, scaleY: number)
  122. /**
  123. * @en
  124. * Slides the guide sign node, i.e., move from one position to another. This method suits the game which needs a slide guide. Note this method only works for hand or arrow type of guide sign.
  125. * @param slideDistance The slide distance.
  126. * @param slideTime The slide time.
  127. * @zh
  128. * 滑动引导图片,即从一个位置移动到另一个位置,适用于需要进行滑动引导的游戏。注意该方法只对手指或箭头类型的引导图片有效。
  129. * @param slideDistance 滑动位移。
  130. * @param slideTime 滑动时间。
  131. */
  132. // slideGuideSign(slideDistance: cc.Vec3, slideTime: number=2)
  133. /**
  134. * @en
  135. * Moves the guide sign node up and down,i.e., like poking. Note this method only works for hand or arrow type of guide sign.
  136. * @zh
  137. * 让引导图片上下运动,即拥有戳戳戳的效果。注意该方法只对手指或箭头类型的引导图片有效。
  138. */
  139. // makeGuideSignMoveUpAndDown()
  140. /**
  141. * @en
  142. * Sets the rotation of guide sign node. The default value is 90, i.e., 90°. Note this method only works for hand or arrow type of guide sign.
  143. * @zh
  144. * 设置引导图片的旋转角度,默认旋转值为90,即绕z轴旋转90°。注意该方法只对手指或箭头类型的引导图片有效。
  145. */
  146. // setGuideSignRotation(r: number=90)
  147. /**
  148. * @en
  149. * Sets the position of guide sign on Canvas.
  150. * @zh
  151. * 设置引导图片在画布上的位置。
  152. */
  153. // setGuideSignPos(pos: cc.Vec3)
  154. /**
  155. * @en
  156. * Stops the guide sign tween.
  157. * @zh
  158. * 停止引导图片缓动。
  159. */
  160. // stopGuideSignTween()
  161. /**
  162. * @en
  163. * Is to make the guide sign fly to the next node position after each guide. If false, the guide sign will hide, and show at next guide.
  164. * @zh
  165. * 完成一次引导后,是否让引导图片飞到下一个被引导节点的位置上。如果是false,则引导图片会先被隐藏,下次引导时再显示出来。
  166. */
  167. // setGuideSignFly(isFlying: boolean=false)
  168. /**
  169. * @en
  170. * Sets flying tween duration. The default is 0.3 second.
  171. * @zh
  172. * 设置飞行缓动持续时间。
  173. */
  174. // setGuideSignFlyingDuration(duration: number=0.3)
  175. /**
  176. * @en
  177. * Sets the interval between two key-down operations, 1.5 seconds by default. For example, if a user presses Ctrl, and then presses G within 1.5 seconds, We see them as combined keys. If over 1.5 seconds, then we see the user presses G only.
  178. * @zh
  179. * 设置两次按键之间的时间间隔,默认是1.5秒。比如用户先按下Ctrl键,并在1.5秒内按下G键,则判断用户按下了组合键。如果超过1.5秒,则判断为只按下了G键。
  180. */
  181. // setKeyDownInterval(interval: number)
  182. /**
  183. * @en
  184. * Is to enable the typing effect.
  185. * @zh
  186. * 是否开启打字机效果。
  187. */
  188. // setTypingEnabled(isEnabled: boolean)
  189. import {Data, Mgr} from '../GameControl'
  190. import {UI} from '../enums/UI'
  191. import {ConstValue} from '../data/ConstValue'
  192. import {ccUtils} from '../utils/ccUtils'
  193. import {UserGuideConfig} from '../config/UserGuideConfig'
  194. /**
  195. * @en
  196. * Typing interval (second) used in schedule, 0.05 second by default.
  197. * @zh
  198. * 设置打字机效果打字的时间间隔(秒),默认是0.05秒。
  199. */
  200. // setTypingInterval(interval: number)
  201. const {ccclass} = cc._decorator
  202. @ccclass
  203. export default class UserGuide extends cc.Component {
  204. /**
  205. * @en
  206. * The temp value for current step.
  207. * @zh
  208. * 用于记录当前引导步数。
  209. */
  210. currentStepTemp = 1
  211. /**
  212. * @en
  213. * The temp value for text pos.
  214. * @zh
  215. * 记录文本显示位置。
  216. */
  217. textPosTemp: cc.Vec3 | string = 'follow'
  218. /**
  219. * @en
  220. * The interval between two key-down operations.
  221. * @zh
  222. * 两次按键时间间隔。
  223. */
  224. keyDownInterval = 1.5
  225. /**
  226. * @en
  227. * Is to enable the typing effect, false by default.
  228. * @zh
  229. * 是否开启打字效果,默认不开启。
  230. */
  231. isTyping = false
  232. /**
  233. * @en
  234. * Typing interval (second) used in schedule.
  235. * @zh
  236. * 打字机效果打字的时间间隔(秒)。
  237. */
  238. typingInterval = 0.05
  239. /**
  240. * @en
  241. * Guide sprite rotation.
  242. * @zh
  243. * 引导图片角度。
  244. */
  245. guideSignRotation = 90
  246. /**
  247. * @en
  248. * Schedule count.
  249. * @zh
  250. * 调度次数。
  251. */
  252. scheduleCount = 0
  253. /**
  254. * @en
  255. * The temp value for guide text.
  256. * @zh
  257. * 引导文本副本。
  258. */
  259. guideTextTemp = ''
  260. /**
  261. * @en
  262. * Is to enable guide sign node tween.
  263. * @zh
  264. * 引导图片缓动是否开启。
  265. */
  266. isGuideSignTweenEnabled = false
  267. /**
  268. * @en
  269. * Current tween on guide sign node.
  270. * @zh
  271. * 引导图片缓动实例。
  272. */
  273. guideSignTween = null
  274. /**
  275. * @en
  276. * The tween type on guide sign node.
  277. * @zh
  278. * 引导图片的缓动类型。
  279. */
  280. guideSignTweenType = ''
  281. /**
  282. * @en
  283. * Is to make the guide sign fly to the next node position after each guide. If false, the guide sign will hide, and show at next guide.
  284. * @zh
  285. * 完成一次引导后,是否让引导图片飞到下一个被引导节点的位置上。如果是false,则引导图片会先被隐藏,下次引导时再显示出来。
  286. */
  287. isGudieSignFlying = false
  288. /**
  289. * @en
  290. * Guide sign flying tween.
  291. * @zh
  292. * 引导图片飞行缓动。
  293. */
  294. guideSignFlyingTween = null
  295. /**
  296. * @en
  297. * Guide sign flying tween duration.
  298. * @zh
  299. * 引导图片飞行缓动持续时间。
  300. */
  301. flyingTweenDuration = 0.3
  302. /**
  303. * @en
  304. * Is guide sign finished flying.
  305. * @zh
  306. * 引导图片飞行是否结束。
  307. */
  308. isFlyingFinised = true
  309. /**
  310. * @en
  311. * The data of slide tween on guide sign node。
  312. * @zh
  313. * 滑动缓动数据。
  314. */
  315. guideSignSlideTweenData = {
  316. slideDistance: null,
  317. slideTime: 0.5,
  318. }
  319. /**
  320. * @en
  321. * Is to guide by group.
  322. * @zh
  323. * 是否为分组引导。
  324. */
  325. isGuidedByGroup = false
  326. /**
  327. * @en
  328. * Saves the step when guiding by group.
  329. * @zh
  330. * 记录分组引导步数。
  331. */
  332. stepIndexInArray = 0
  333. /**
  334. * @en
  335. * The temp value for current step array.
  336. * @zh
  337. * 当前引导分组。
  338. */
  339. currentStepArrayTemp = []
  340. /**
  341. * @en
  342. * The schedule callback, used to update some properties(pos, size...) of mask node and guide sign node.
  343. * @zh
  344. * 计时器回调函数,用来更新遮罩和引导图片的位置。
  345. */
  346. setMaskAndGuideSpritePosAndSizeScheduleCallBack = null
  347. /**
  348. * @en
  349. * The guide data generated by user guide extension.
  350. * @zh
  351. * 用户通过插件生成的引导数据。
  352. */
  353. guideData = %s
  354. /**
  355. * @en
  356. * The language type of guide text, 'zh' by default, the other value is 'en'.
  357. * @zh
  358. * 引导文本语言种类,默认是'zh',其他可选值为'en'。
  359. */
  360. guideTextLang = 'zh'
  361. /**
  362. * @en
  363. * The UITransform component of canvas.
  364. * @zh
  365. * 画布的UITransform组件。
  366. */
  367. canvasUITransform = {width: 1920, height: 1080}
  368. /**
  369. * @en
  370. * The mask node which is generated dynamically.
  371. * @zh
  372. * 动态创建的遮罩节点。
  373. */
  374. maskNode: cc.Node = null!
  375. /**
  376. * @en
  377. * The child node of mask node, which has a BlockInputEvents component.
  378. * @zh
  379. * 遮罩节点下的子节点,含有BlockInputEvents组件。
  380. */
  381. blockBgNode: cc.Node = null!
  382. /**
  383. * @en
  384. * The guide sign node which is generated dynamically.
  385. * @zh
  386. * 动态创建的引导图片节点。
  387. */
  388. guideSignSpriteNode: cc.Node = null!
  389. /**
  390. * @en
  391. * Saves the position of guide sign set by developers.
  392. * @zh
  393. * 保存开发者设置的引导图片位置。
  394. */
  395. guideSignPosTemp: cc.Vec3 = null
  396. /**
  397. * @en
  398. * The guide text background node which is generated dynamically.
  399. * @zh
  400. * 动态创建的文本背景图片节点。
  401. */
  402. guideTextBgSpriteNode: cc.Node = null!
  403. /**
  404. * @en
  405. * The guide text node which is generated dynamically.
  406. * @zh
  407. * 动态创建的文本节点。
  408. */
  409. guideTextLabelNode: cc.Node = null!
  410. //角色节点
  411. roleNode: cc.Node = null!
  412. //角色spine
  413. roleSpine: sp.SkeletonData = null!
  414. // 图片bundle
  415. texBundle: cc.AssetManager.Bundle = null!
  416. // handSp
  417. handSp: cc.SpriteFrame = null!
  418. // 箭头
  419. arrowSp: cc.SpriteFrame = null!
  420. onLoad() {}
  421. start() {}
  422. init(roleSpine: sp.SkeletonData, texBundle: cc.AssetManager.Bundle) {
  423. this.guideData.nodesAndTexts = Object.values(UserGuideConfig)
  424. this.roleSpine = roleSpine
  425. this.texBundle = texBundle
  426. this.createNodes()
  427. this.setGuideTextCustomFont('ttf/COMICBD')
  428. this.makeGuideSignMoveUpAndDown()
  429. this.setTypingEnabled(false)
  430. this.guideData.nodesAndTexts.forEach((nodeAndText: any) => {
  431. nodeAndText.guideText = Mgr.i18n.getLabel(nodeAndText.guideText)
  432. })
  433. }
  434. /**
  435. * @en
  436. * Creates nodes dynamically needed for user guide.
  437. * @zh
  438. * 动态创建新手引导需要用到的节点。
  439. */
  440. createNodes() {
  441. this.createMaskNode()
  442. this.createBlockBgNode()
  443. this.createGuideSignSpriteNode()
  444. this.createGuideTextBgSpriteNode()
  445. this.createGuideTextLabelNode()
  446. }
  447. /**
  448. * @en
  449. * Creates mask node dynamically.
  450. * @zh
  451. * 动态创建遮罩节点。
  452. */
  453. createMaskNode() {
  454. this.maskNode = new cc.Node('Mask Node')
  455. this.maskNode.active = false
  456. this.maskNode.addComponent(cc.Mask)
  457. let maskSpNode = new cc.Node('Mask Sprite Node')
  458. let spriteComp = maskSpNode.addComponent(cc.Sprite)
  459. spriteComp.type = cc.Sprite.Type.SLICED
  460. this.texBundle.load('Public/block4', cc.SpriteFrame, (err: any, spriteFrame: cc.SpriteFrame) => {
  461. spriteComp.spriteFrame = spriteFrame
  462. })
  463. this.maskNode.addChild(maskSpNode)
  464. maskSpNode.setSiblingIndex(Number.MAX_SAFE_INTEGER)
  465. this.node.addChild(this.maskNode)
  466. }
  467. /**
  468. * @en
  469. * Creates the child node of mask node dynamically. This node can block all input events.
  470. * @zh
  471. * 创建可排除所有输入事件的节点,作为遮罩节点的子节点。
  472. */
  473. createBlockBgNode() {
  474. this.blockBgNode = new cc.Node('Block Bg Node')
  475. this.blockBgNode.addComponent(cc.BlockInputEvents)
  476. let spriteComp = this.blockBgNode.addComponent(cc.Sprite)
  477. this.blockBgNode.color = new cc.Color(0, 0, 0)
  478. this.blockBgNode.opacity = 100
  479. let self = this
  480. this.texBundle.load('Public/block2', cc.SpriteFrame, (err: any, spriteFrame: cc.SpriteFrame) => {
  481. spriteComp.spriteFrame = spriteFrame
  482. self.blockBgNode.width = this.canvasUITransform.width * 10
  483. self.blockBgNode.height = this.canvasUITransform.height * 10
  484. })
  485. this.maskNode.addChild(this.blockBgNode)
  486. this.blockBgNode.setSiblingIndex(0)
  487. }
  488. /**
  489. * @en
  490. * Creates the guide sign node and loads the sprite dynamically.
  491. * @zh
  492. * 动态创建引导图片节点并设置引导图片。
  493. */
  494. createGuideSignSpriteNode() {
  495. this.guideSignSpriteNode = new cc.Node('Guide Sign Sprite Node')
  496. this.guideSignSpriteNode.active = false
  497. let self = this
  498. let spriteComp = this.guideSignSpriteNode.addComponent(cc.Sprite)
  499. // if (this.guideData.guideSignType.includes('frame')) {
  500. // spriteComp.type = cc.Sprite.Type.SLICED
  501. //
  502. // }
  503. this.texBundle.load('Public/arrow_5', cc.SpriteFrame, (err: any, spriteFrame: cc.SpriteFrame) => {
  504. spriteComp.spriteFrame = spriteFrame
  505. self.arrowSp = spriteFrame
  506. //this.adjustGuideSignSpriteNode(1)
  507. })
  508. this.texBundle.load('UserGuideUI/guide_finger', cc.SpriteFrame, (err: any, spriteFrame: cc.SpriteFrame) => {
  509. self.handSp = spriteFrame
  510. //this.adjustGuideSignSpriteNode(1)
  511. })
  512. this.node.addChild(this.guideSignSpriteNode)
  513. }
  514. /**
  515. * @en
  516. * Creates the guide text background node and loads the sprite dynamically.
  517. * @zh
  518. * 创建文本背景节点并设置图片。
  519. */
  520. createGuideTextBgSpriteNode() {
  521. this.guideTextBgSpriteNode = new cc.Node('Text Bg Sprite Node')
  522. this.guideTextBgSpriteNode.active = false
  523. this.roleNode = new cc.Node('Text Role Node')
  524. this.roleNode.active = false
  525. this.roleNode.scale = 0.75
  526. let self = this
  527. let spriteComp = this.guideTextBgSpriteNode.addComponent(cc.Sprite)
  528. spriteComp.type = cc.Sprite.Type.SLICED
  529. self.textPosTemp == 'bottom'
  530. ? self.setGuideTextBgSpriteSizeByCanvasSize()
  531. : self.setGuideTextBgSpriteSizeByTextLength()
  532. this.texBundle.load('Public/preview_bottom_1', cc.SpriteFrame, (err: any, spriteFrame: cc.SpriteFrame) => {
  533. spriteComp.spriteFrame = spriteFrame
  534. // self.textPosTemp == 'bottom'
  535. // ? self.setGuideTextBgSpriteSizeByCanvasSize()
  536. // : self.setGuideTextBgSpriteSizeByTextLength()
  537. })
  538. this.node.addChild(this.roleNode)
  539. let spCom = this.roleNode.addComponent(sp.Skeleton)
  540. this.roleNode.setSiblingIndex(Number.MAX_SAFE_INTEGER - 1)
  541. spCom.skeletonData = this.roleSpine
  542. this.node.addChild(this.guideTextBgSpriteNode)
  543. }
  544. /**
  545. * @en
  546. * Creates the guide text node dynamically.
  547. * @zh
  548. * 创建引导文本节点。
  549. */
  550. createGuideTextLabelNode() {
  551. this.guideTextLabelNode = new cc.Node('Guide Text Label Node')
  552. this.guideTextLabelNode.width = 100
  553. this.guideTextLabelNode.height = 40
  554. let labelComp = this.guideTextLabelNode.addComponent(cc.Label)
  555. labelComp.horizontalAlign = cc.Label.HorizontalAlign.LEFT
  556. labelComp.verticalAlign = cc.Label.VerticalAlign.TOP
  557. labelComp.overflow = cc.Label.Overflow.SHRINK
  558. this.guideTextLabelNode.color = new cc.Color(255, 255, 255)
  559. labelComp.fontSize = 36
  560. labelComp.lineHeight = 40
  561. let labelOutComp = this.guideTextLabelNode.addComponent(cc.LabelOutline)
  562. labelOutComp.color = new cc.Color(38, 17, 12)
  563. labelOutComp.width = 3
  564. this.guideTextBgSpriteNode.addChild(this.guideTextLabelNode)
  565. // Moves the guide text node downwards a litte bit to make it shown at center.
  566. // 稍微往下移动一点显得在图片上居中。
  567. this.guideTextLabelNode.setPosition(0, -5, 0)
  568. }
  569. /**
  570. * @en
  571. * Hides all nodes related to user guide.
  572. * @zh
  573. * 隐藏与引导相关的所有节点。
  574. */
  575. hideGuide() {
  576. // 隐藏与引导相关的所有节点
  577. this.maskNode.active = false
  578. this.guideSignSpriteNode.active = false
  579. this.guideTextBgSpriteNode.active = false
  580. this.roleNode.active = false
  581. }
  582. /**
  583. * @en
  584. * Slides the guide sign node, i.e., move from one position to another. This method suits the game which needs a slide guide. Note this method only works for hand or arrow type of guide sign.
  585. * @param slideDistance The slide distance.
  586. * @param slideTime The slide time.
  587. * @zh
  588. * 滑动引导图片,即从一个位置移动到另一个位置,适用于需要进行滑动引导的游戏。注意该方法只对手指或箭头类型的引导图片有效。
  589. * @param slideDistance 滑动位移。
  590. * @param slideTime 滑动时间。
  591. */
  592. slideGuideSign(slideDistance: cc.Vec3, slideTime: number = 2) {
  593. if (this.guideData.guideSignType.includes('hand') || this.guideData.guideSignType.includes('arrow')) {
  594. return
  595. }
  596. this.isGuideSignTweenEnabled = true
  597. this.guideSignTweenType = 'slide'
  598. this.guideSignSlideTweenData = {
  599. slideDistance: slideDistance,
  600. slideTime: slideTime,
  601. }
  602. }
  603. /**
  604. * @en
  605. * Is to make the guide sign fly to the next node position after each guide. If false, the guide sign will hide, and show at next guide.
  606. * @param isFlying Whether to make the guide sign fly to the target node.
  607. * @zh
  608. * 完成一次引导后,是否让引导图片飞到下一个被引导节点的位置上。如果是false,则引导图片会先被隐藏,下次引导时再显示出来。
  609. * @param isFlying 是否让引导图片飞到目标节点上
  610. */
  611. setGuideSignFly(isFlying: boolean = false) {
  612. this.isGudieSignFlying = isFlying
  613. }
  614. /**
  615. * @en
  616. * Sets flying tween duration. The default is 0.3 second.
  617. * @param duration Flying tween duration
  618. * @zh
  619. * 设置飞行缓动持续时间。
  620. * @param duration 飞行缓动持续时间,默认0.3秒。
  621. */
  622. setGuideSignFlyingDuration(duration: number = 0.3) {
  623. this.flyingTweenDuration = duration
  624. }
  625. /**
  626. * @en
  627. * Moves the guide sign node up and down,i.e., like poking. Note this method only works for hand or arrow type of guide sign.
  628. * @zh
  629. * 让引导图片上下运动,即拥有戳戳戳的效果。注意该方法只对手指或箭头类型的引导图片有效。
  630. */
  631. makeGuideSignMoveUpAndDown() {
  632. if (this.guideData.guideSignType.includes('hand') && this.guideData.guideSignType.includes('arrow')) {
  633. return
  634. }
  635. this.isGuideSignTweenEnabled = true
  636. this.guideSignTweenType = 'updown'
  637. }
  638. /**
  639. * @en
  640. * Sets the rotation of guide sign node. The default value is 90, i.e., 90°. Note this method only works for hand or arrow type of guide sign.
  641. * @zh
  642. * 设置引导图片的旋转角度,默认旋转值为90,即绕z轴旋转90°。注意该方法只对手指或箭头类型的引导图片有效。
  643. */
  644. setGuideSignRotation(r: number = 90) {
  645. if (this.guideData.guideSignType.includes('hand') && this.guideData.guideSignType.includes('arrow')) {
  646. return
  647. }
  648. this.guideSignRotation = r
  649. }
  650. /**
  651. * @en
  652. * Sets the position of guide sign on Canvas.
  653. * @zh
  654. * 设置引导图片在画布上的位置。
  655. */
  656. setGuideSignPos(pos: cc.Vec3) {
  657. this.guideSignPosTemp = pos
  658. }
  659. startGuideSignTween() {
  660. // Stops the current tween and restarts.
  661. // 先停止之前的缓动,然后再重新开始。
  662. if (this.guideSignTween) {
  663. this.guideSignTween.stop()
  664. }
  665. if (this.guideSignTweenType == 'slide') {
  666. // Slides the guide sign node and make it back to original position quickly, then slides again.
  667. // 滑动引导图片,滑动过后快速回到原来的位置,然后继续滑动。
  668. this.initGuideSignSlideTween()
  669. } else if (this.guideSignTweenType == 'updown') {
  670. // Moves the guide sign node up and down.
  671. // 让引导图片上下运动。
  672. this.initGuideSignUpDownTween()
  673. }
  674. // Starts the tween.
  675. // 开启引导图片缓动。
  676. this.guideSignTween.start()
  677. }
  678. /**
  679. * @en
  680. * Slides the guide sign node and make it back to original position quickly, then slides again.
  681. * @zh
  682. * 滑动引导图片,滑动过后快速回到原来的位置,然后继续滑动。
  683. */
  684. initGuideSignSlideTween() {
  685. let slideTime = this.guideSignSlideTweenData.slideTime
  686. let slideDistance = this.guideSignSlideTweenData.slideDistance
  687. this.guideSignTween = cc
  688. .tween(this.guideSignSpriteNode)
  689. .by(slideTime, {position: slideDistance})
  690. .by(slideTime / 5, {position: new cc.Vec3(-slideDistance.x, -slideDistance.y, -slideDistance.z)})
  691. .union()
  692. .repeatForever()
  693. }
  694. /**
  695. * @en
  696. * Moves the guide sign node up and down.
  697. * @zh
  698. * 让引导图片上下运动。
  699. */
  700. initGuideSignUpDownTween() {
  701. this.guideSignTween = cc
  702. .tween(this.guideSignSpriteNode)
  703. .by(0.5, {position: new cc.Vec3(0, -10, 0)})
  704. .by(0.5, {position: new cc.Vec3(0, 10, 0)})
  705. .union()
  706. .repeatForever()
  707. }
  708. /**
  709. * @en
  710. * Stops the guide sign tween.
  711. * @zh
  712. * 停止引导图片缓动。
  713. */
  714. stopGuideSignTween() {
  715. if (this.guideSignTween) {
  716. this.isGuideSignTweenEnabled = false
  717. this.guideSignTween.stop()
  718. this.guideSignTween = null
  719. this.guideSignTweenType = ''
  720. this.guideSignSlideTweenData = {
  721. slideDistance: null,
  722. slideTime: 0.5,
  723. }
  724. }
  725. }
  726. /**
  727. * @en
  728. * Sets the scale of guide sign.
  729. * @zh
  730. * 设置引导图片缩放值。
  731. */
  732. setGuideSignScale(scaleX: number, scaleY: number) {
  733. this.guideSignSpriteNode.setScale(scaleX, scaleY, 0)
  734. }
  735. /**
  736. * @en
  737. * Sets the color of guide text, black by default.
  738. * @zh
  739. * 设置引导文本颜色,默认为黑色。
  740. */
  741. setGuideTextColor(color: cc.Color) {
  742. this.guideTextLabelNode.color = color
  743. }
  744. /**
  745. * @en
  746. * Sets the font size of guide text, 28 by default.
  747. * @zh
  748. * 设置引导文本字体大小,默认为28。
  749. */
  750. setGuideTextFontSize(fontSize: number) {
  751. this.guideTextLabelNode.getComponent(cc.Label).fontSize = fontSize
  752. }
  753. /**
  754. * @en
  755. * Sets the system font of guide text.
  756. * @param sysFontName System font name
  757. * @zh
  758. * 设置引导文本的系统字体。
  759. * @param sysFontName 系统字体名称
  760. */
  761. setGuideTextSystemFont(sysFontName: string) {
  762. this.guideTextLabelNode.getComponent(cc.Label).useSystemFont = true
  763. this.guideTextLabelNode.getComponent(cc.Label).fontFamily = sysFontName
  764. }
  765. /**
  766. * @en
  767. * Sets the custom font of guide text.
  768. * @param pathInRes The path of the custom font in resources folder. The format should be ttf and the path should end without the extension name .ttf.
  769. * @zh
  770. * @param pathInRes 自定义字体在resources文件夹中的路径,字体格式为ttf,注意路径最后不带后缀名.ttf。
  771. * 设置引导文本自定义字体。
  772. */
  773. setGuideTextCustomFont(pathInRes: string) {
  774. this.guideTextLabelNode.getComponent(cc.Label).useSystemFont = false
  775. cc.resources.load(pathInRes, cc.Font, (err: any, font: cc.Font) => {
  776. this.guideTextLabelNode.getComponent(cc.Label).font = font
  777. })
  778. }
  779. /**
  780. * @en
  781. * Sets the line height of guide text, 28 by default.
  782. * @zh
  783. * 设置引导文本行高,默认为40。
  784. */
  785. setGuideTextLineHeight(lineHeight: number) {
  786. this.guideTextLabelNode.getComponent(cc.Label).lineHeight = lineHeight
  787. }
  788. /**
  789. * @en
  790. * Sets the position of guide text.
  791. * @param textPos Where to show the guide text. Choices are Vec3 type of value (position on Canvas), or string type of value: 'follow', 'center' and 'bottom'. 'follow' means showing next to the target node, 'center' means showing in the center of Canvas and 'bottom' means showing at the bottom of Canvas.
  792. * @zh
  793. * 设置引导文本位置。
  794. * @param textPos 要在哪里显示引导文本,可以是Vec3类型的值,即在画布上的具体位置,或者是字符串类型的值'follow'、'center'和'bottom'。'follow'表示显示在目标节点周围,'center'表示显示在画布中间,'bottom'表示显示在画布底部。
  795. */
  796. setGuideTextPos(textPos: cc.Vec3 | string = 'follow') {
  797. this.textPosTemp = textPos
  798. }
  799. /**
  800. * @en
  801. * Sets the language type of guide text, 'zh' by default, the other value is 'en'.
  802. * @zh
  803. * 设置引导文本语言种类,默认是'zh',其他可选值为'en'。
  804. */
  805. setGuideTextLang(lang: string = 'zh') {
  806. this.guideTextLang = lang
  807. }
  808. /**
  809. * @en
  810. * Sets the scale of guide text background node.
  811. * @zh
  812. * 设置引导文本背景缩放值。
  813. */
  814. setGuideTextBackgroundScale(scaleX: number, scaleY: number) {
  815. this.guideTextBgSpriteNode.setScale(scaleX, scaleY, 0)
  816. // The scale of bakcground shouldn't influence the child label node.
  817. // 让Label节点不受父节点影响
  818. this.guideTextLabelNode.setScale(1 / scaleX, 1 / scaleY, 0)
  819. // Label is a little bit smaller than the background node.
  820. // Label大小稍微比背景图片小点。
  821. this.guideTextLabelNode.width = (this.guideTextBgSpriteNode.width * scaleX) / 1.1
  822. this.guideTextLabelNode.width = (this.guideTextBgSpriteNode.height * scaleY) / 1.1
  823. }
  824. /**
  825. * @en
  826. * Sets the mask color, black and half transparent by default.
  827. * @zh
  828. * 设置遮罩层颜色,默认为黑色半透明。
  829. */
  830. setMaskColor(color: cc.Color) {
  831. this.blockBgNode.color = color
  832. this.blockBgNode.opacity = color.a
  833. }
  834. /**
  835. * @en
  836. * Sets the mask shape, rect by default.
  837. * @param shape 'rect', 'ellipse' or 'sprite stencil'
  838. * @param spriteFrame This parameter must accept a SpriteFrame type of value When the shape value is 'sprite stencil'.
  839. * @zh
  840. * 设置遮罩挖洞形状,默认为矩形。
  841. * @param shape 'rect','ellipse'或者'sprite stencil'
  842. * @param spriteFrame 当遮罩挖洞形状为'sprite stencil'时,该参数必须接收一个SpriteFrame类型的值。
  843. */
  844. setMaskShape(shape: string, spriteFrame: cc.SpriteFrame = null) {
  845. if (shape == 'rect') {
  846. this.maskNode.getComponent(cc.Mask).type = cc.Mask.Type.RECT
  847. } else if (shape == 'ellipse') {
  848. this.maskNode.getComponent(cc.Mask).type = cc.Mask.Type.ELLIPSE
  849. } else if (shape == 'sprite stencil' && spriteFrame) {
  850. this.maskNode.getComponent(cc.Mask).type = cc.Mask.Type.IMAGE_STENCIL
  851. this.maskNode.getComponent(cc.Mask).spriteFrame = spriteFrame
  852. }
  853. }
  854. /**
  855. * @en
  856. * Sets the interval between two key-down operations, 1.5 seconds by default.
  857. * @zh
  858. * 设置两次按键之间的时间间隔,默认是1.5秒。
  859. */
  860. setKeyDownInterval(interval: number) {
  861. this.keyDownInterval = interval
  862. }
  863. /**
  864. * @en
  865. * Is to enable the typing effect.
  866. * @zh
  867. * 是否开启打字机效果。
  868. */
  869. setTypingEnabled(isEnabled: boolean) {
  870. this.isTyping = isEnabled
  871. }
  872. /**
  873. * @en
  874. * Typing interval (second) used in schedule, 0.05 second by default.
  875. * @zh
  876. * 设置打字机效果打字的时间间隔(秒),默认是0.05秒。
  877. */
  878. setTypingInterval(interval: number) {
  879. this.typingInterval = interval
  880. }
  881. /**
  882. * @en
  883. * Shows the guide by group.
  884. * @param stepArray The guide steps array, [1, 3, 5] means to execute the fist, the third and the fifth guide step. You may also pass an alias array, e.g., ['alias of guide step1', 'alias of guide step 2'];
  885. * @param callback Takes a callback function. which will be called the user completes the current guide.
  886. * @zh
  887. * 按分组显示引导。
  888. * @param stepArray 要执行各个引导步骤,比如传入[1, 3, 5]表示一次执行第一、第三和第五步引导。也可以传入别名数组['第一步引导别名', '第二步引导别名']。
  889. * @param callback 接收一个回调函数,当用户完成当前引导后会执行该回调函数。
  890. */
  891. showGuideByGroup(stepArray: Array<number | string>, callback: Function = null) {
  892. // Return if the step array is empty.
  893. // 如果引导步骤为空,则直接返回。
  894. if (!stepArray.length) {
  895. return
  896. }
  897. // Sets some related variables to show we are in group guiding.
  898. // 设置相关变量,表明现在正在进行分组引导。
  899. this.isGuidedByGroup = true
  900. this.currentStepArrayTemp = stepArray
  901. // Executes the fist guide step in the group.
  902. // 执行分组中的第一步引导
  903. this.showGuide(stepArray[this.stepIndexInArray], true, callback)
  904. }
  905. /**
  906. * @en
  907. * Shows guides or a single guide.
  908. * @param step Which step to be guided, 1 by default. You may also pass the alias name of the step.
  909. * @param isAuto Is to play the next guide automatically, false by default.
  910. * @param callback Takes a callback function. which will be called the user completes the current guide. Only works when the parameter isAuto is false. Should use this parameter in single step guide type.
  911. *
  912. * @zh
  913. * 显示连续或单步引导。
  914. * @param step 新手引导的第几步,默认是第一步。也可以传入该引导步骤的别名。
  915. * @param isAuto 完成当前引导后是否自动播放下一个引导。
  916. * @param callback 接收一个回调函数,当用户完成当前引导后会执行该回调函数。只有isAuto为false时才有效,适用于单步引导。
  917. */
  918. showGuide(step: number | string, isAuto: boolean = false, callback: Function = null) {
  919. if (!step) {
  920. console.log('请设置参数step的值。')
  921. console.log("Please set parameter step's value.")
  922. return
  923. }
  924. // Change alias to index.
  925. // 将别名转换成索引。
  926. if (typeof step == 'string') {
  927. let temp = step
  928. step = this.changeAliasToIndex(step)
  929. if (step == 0) {
  930. console.log(`step名称${temp}不存在。`)
  931. console.log(`The step alias ${temp} does not exist.`)
  932. return
  933. }
  934. }
  935. // If a developer passes a step value bigger than the biggest step number, then cleans related content and retuen.
  936. // 如果开发者传入的步数大于插件中设置的步数,则清理相关内容后返回。
  937. if (step > this.guideData.nodesAndTexts.length) {
  938. // Delete the guide sign (repeatForever) tween to prevent memory usage.
  939. // 需要删除引导图片的repeatForever缓动,防止占用内存。
  940. if (this.isGuideSignTweenEnabled) {
  941. this.stopGuideSignTween()
  942. }
  943. return
  944. }
  945. let curData = this.guideData.nodesAndTexts[step - 1]
  946. // If path and key are both null, then we are having a text guide only.
  947. // 如果路径和键都不存在,则说明是说明引导。
  948. if (curData.uiType) {
  949. //this.showOnlyTextGuide(step, isAuto, callback)
  950. Mgr.ui.show(
  951. +curData.uiType > 100 ? UI.ModOpenUI : UI.UserGuideUI,
  952. Object.assign({callback: callback}, curData),
  953. )
  954. return
  955. }
  956. // Saves the current guide step, and it will be used in resources.load().
  957. // 保存当前引导步数,用在resources.load()方法中。
  958. this.currentStepTemp = step
  959. //重新设置当前引导类型
  960. this.guideData.guideSignType = `${curData.arrowType == 1 ? 'arrow' : ''}_${curData.showTextBg ? 'frame' : ''}_${
  961. curData.arrowType == 2 ? 'hand' : ''
  962. }`
  963. // Is touch guide or key guide.
  964. // 判断是触摸引导还是按键引导。
  965. if (!this.guideData.nodesAndTexts[step - 1].key) {
  966. let targetNodePath = this.guideData.nodesAndTexts[step - 1].path
  967. if (!targetNodePath) {
  968. console.error(`未找到uuid为${this.guideData.nodesAndTexts[step - 1].path}的节点`)
  969. console.error(`Can't find the node whose uuid is ${this.guideData.nodesAndTexts[step - 1].path}`)
  970. return
  971. }
  972. let targetNode = cc.find(targetNodePath)
  973. this.showNodeAndTextGuide(targetNode, step, isAuto, callback)
  974. } else {
  975. let keys = this.guideData.nodesAndTexts[step - 1].key.split('+')
  976. this.showKeyAndTextGuide(keys, step, isAuto, callback)
  977. }
  978. }
  979. /**
  980. * @en
  981. * Change alias to index.
  982. * @zh
  983. * 将别名转换成索引。
  984. */
  985. changeAliasToIndex(step: string) {
  986. for (let i = 0; i < this.guideData.nodesAndTexts.length; i++) {
  987. if (this.guideData.nodesAndTexts[i].alias == step) {
  988. return i + 1
  989. }
  990. }
  991. return 0
  992. }
  993. /**
  994. * @en
  995. * Shows the next guide.
  996. * @zh
  997. * 显示下一步引导。
  998. */
  999. goToNextGuide(step: number, isAuto: boolean, callback: Function = null) {
  1000. // If it is guided by group, then gets the next guide step number from the guide array.
  1001. // 判断是否为分组引导,是的话则需要从引导分组中获取下一步引导序号。
  1002. if (this.isGuidedByGroup) {
  1003. this.stepIndexInArray += 1
  1004. // If it is the last step, resets all related variables and executes the callback.
  1005. // 如果已经是最后一步引导,则重置相关变量,执行回调。
  1006. if (this.stepIndexInArray >= this.currentStepArrayTemp.length) {
  1007. this.stepIndexInArray = 0
  1008. this.isGuidedByGroup = false
  1009. this.currentStepArrayTemp = []
  1010. // Delete the guide sign (repeatForever) tween to prevent memory usage.
  1011. // 需要删除引导图片的repeatForever缓动,防止占用内存
  1012. if (this.isGuideSignTweenEnabled) {
  1013. this.stopGuideSignTween()
  1014. }
  1015. // Executes the callback.
  1016. // 执行回调。
  1017. if (callback) {
  1018. callback()
  1019. }
  1020. }
  1021. // If it is not the last step, use the next guide number from array.
  1022. // 如果不是最后一步引导,则使用数组中的下一个引导数字。
  1023. else {
  1024. this.showGuide(this.currentStepArrayTemp[this.stepIndexInArray], isAuto, callback)
  1025. }
  1026. }
  1027. // If it is not guided by group, then adds 1 on the current step number.
  1028. // 如果不是分组引导,则将引导步骤加上1。
  1029. else {
  1030. this.showGuide((step += 1), isAuto, callback)
  1031. }
  1032. }
  1033. /**
  1034. * @en
  1035. * Shows the guide with text only.
  1036. * @zh
  1037. * 只有文本的引导,文本默认显示在屏幕中间。
  1038. */
  1039. showOnlyTextGuide(step: number, isAuto: boolean, callback: Function = null) {
  1040. // Show related nodes.
  1041. // 显示引导相关节点。
  1042. // this.maskNode.active = true
  1043. // this.guideTextBgSpriteNode.active = true
  1044. // Sets the callback function.
  1045. // 设置回调函数。
  1046. let touchStartCallback = () => {
  1047. this.hideGuide()
  1048. if (isAuto) {
  1049. this.goToNextGuide(step, isAuto, callback)
  1050. } else if (callback) {
  1051. callback()
  1052. }
  1053. this.blockBgNode.off(cc.Node.EventType.TOUCH_START, touchStartCallback, this)
  1054. }
  1055. this.blockBgNode.on(cc.Node.EventType.TOUCH_START, touchStartCallback, this)
  1056. // Sets mask. All nodes can not accept click event as there is no target node to be clicked in the guide.
  1057. // 设置遮罩,让所有节点都无法被点击,因为没有在引导中设置要点击的目标节点 this.maskNode.setPosition(new cc.Vec3(0, 0, 0))
  1058. this.maskNode.setSiblingIndex(0)
  1059. this.maskNode.getComponent(cc.Mask).inverted = true
  1060. this.maskNode.width = 0
  1061. this.maskNode.height = 0
  1062. // Shows the guide text.
  1063. // 显示引导文本。
  1064. // this.adjustGuideTextBgSpriteNode()
  1065. // this.adjustGuideTextLabelNode(step)
  1066. }
  1067. /**
  1068. * @en
  1069. * Shows the guide text and the node to be guided.
  1070. * @zh
  1071. * 显示文本和节点引导。
  1072. */
  1073. showNodeAndTextGuide(targetNode: cc.Node, step: number, isAuto: boolean, callback: Function = null) {
  1074. let curData = this.guideData.nodesAndTexts[step - 1]
  1075. // Show related nodes.
  1076. // 显示引导相关节点。
  1077. this.maskNode.active = true
  1078. let maskFrameNode = this.maskNode.children[1]
  1079. maskFrameNode.active = false
  1080. this.guideSignSpriteNode.active = curData.arrowType > 0
  1081. if (this.arrowSp && this.handSp && curData.arrowType > 0) {
  1082. let spArr = [null, this.arrowSp, this.handSp]
  1083. this.guideSignSpriteNode.getComponent(cc.Sprite).spriteFrame = spArr[curData.arrowType]
  1084. }
  1085. this.guideTextBgSpriteNode.active = curData.showTextBg
  1086. this.blockBgNode.active = curData.prevent
  1087. this.roleNode.active = curData.showRole
  1088. if (this.roleNode.active) {
  1089. let spCom = this.roleNode.getComponent(sp.Skeleton)
  1090. spCom.setAnimation(0, 'stand', true)
  1091. }
  1092. // Reset guide sign tween before each guide.
  1093. // 每次引导前重置引导图片飞行缓动
  1094. this.guideSignFlyingTween = null
  1095. // Sets the callback function.
  1096. // 设置点击后的回调函数。
  1097. let touchStartCallback = () => {
  1098. this.hideGuide()
  1099. this.unschedule(this.setMaskAndGuideSpritePosAndSizeScheduleCallBack)
  1100. // this.setMaskAndGuideSpritePosAndSizeScheduleCallBack = null
  1101. if (isAuto) {
  1102. this.goToNextGuide(step, isAuto, callback)
  1103. } else if (callback) {
  1104. callback()
  1105. }
  1106. targetNode.off(cc.Node.EventType.TOUCH_START, touchStartCallback, this)
  1107. }
  1108. if (targetNode.height < ConstValue.CANVAS_HEIGHT) {
  1109. targetNode.on(cc.Node.EventType.TOUCH_START, touchStartCallback, this)
  1110. }
  1111. // Sets mask.
  1112. // 设置遮罩相关属性。
  1113. this.maskNode.setPosition(new cc.Vec3(0, 0, 0))
  1114. this.maskNode.angle = 0
  1115. this.maskNode.setSiblingIndex(0)
  1116. this.maskNode.getComponent(cc.Mask).inverted = true
  1117. // The callback that updates the properties (pos, size...) of mask node and guide sign node.
  1118. // 更新遮罩和引导图片的计时器回调函数。
  1119. this.setMaskAndGuideSpritePosAndSizeScheduleCallBack = () => {
  1120. // Changes the szie of mask hole and guide sign node according to the target node.
  1121. // 根据目标节点改变遮罩挖洞和引导图片的大小。
  1122. this.maskNode.width = targetNode.width * targetNode.scaleX * 1.1
  1123. this.maskNode.height = targetNode.height * targetNode.scaleY * 1.1
  1124. if (targetNode.height < ConstValue.CANVAS_HEIGHT) {
  1125. maskFrameNode.active = true
  1126. maskFrameNode.width = this.maskNode.width + 8
  1127. maskFrameNode.height = this.maskNode.height + 8
  1128. } else {
  1129. //全屏target 默认是全屏无挖孔,点击屏幕任意位置下一步
  1130. this.showOnlyTextGuide(step, isAuto, callback)
  1131. }
  1132. // Changes the mask's position according to the target node.
  1133. // 根据目标节点调整遮罩节点位置。
  1134. this.maskNode.setPosition(ccUtils.convertNode2NodePosAR(targetNode, this.node))
  1135. this.maskNode.angle = targetNode.angle
  1136. // Sets again the size of mask background, in case of the wrong size in some games.
  1137. // 这里再一次设置遮罩背景大小,防止部分游戏逻辑下遮罩背景大小错误的情况。
  1138. this.blockBgNode.width = this.canvasUITransform.width * 10
  1139. this.blockBgNode.height = this.canvasUITransform.height * 10
  1140. // Adjusts the position of guide text background. To ensure that the guide sign node is not covered by guide text background. We need to adjust guide text node before guide sign node.
  1141. // 调整文本背景位置。为了不让引导图片被文本背景遮住,需要先设置文本背景,再设置引导图片。
  1142. this.setGuideTextPos(cc.v3(curData.textBgPos[0], curData.textBgPos[1], 0))
  1143. this.adjustGuideTextBgSpriteNode()
  1144. // Adjust guide sign node. Different guide sign sprites need different adjustments.
  1145. // 调整引导图片,不同引导图片需做不同处理。
  1146. this.setGuideSignRotation(curData.arrowRotation)
  1147. let arrowOffsetX = 0
  1148. if (curData.path.includes('MainUI/leftNode')) arrowOffsetX = Data.main.safeTop
  1149. this.setGuideSignPos(cc.v3(curData.arrowPos[0] + arrowOffsetX, curData.arrowPos[0], 0))
  1150. this.adjustGuideSignSpriteNode(step)
  1151. }
  1152. // Make sure the schedule from last guide is off.
  1153. // 确保上次引导中的计时器关闭
  1154. this.unschedule(this.setMaskAndGuideSpritePosAndSizeScheduleCallBack)
  1155. // If the target node doesn't move, we just need to call the method below once.
  1156. // If the target node moves, the schedule will start soon.
  1157. // 如果节点不移动,遮罩和引导图片的位置设置一次即可。
  1158. // 如果节点是移动的,那之后就会开启计时器。
  1159. this.setMaskAndGuideSpritePosAndSizeScheduleCallBack()
  1160. // Watches the transformation of target node. If target node transforms, starts the schedule and updates the size, position and rotation of mask node and guide sign node.
  1161. // 监听是否有任何变化,如果改变则使用计时器实时更新遮罩和引导图片位置。
  1162. let transformChangedCallback = () => {
  1163. this.schedule(this.setMaskAndGuideSpritePosAndSizeScheduleCallBack, 0.01, cc.macro.REPEAT_FOREVER)
  1164. targetNode.off(cc.Node.EventType.POSITION_CHANGED, transformChangedCallback, this)
  1165. targetNode.off(cc.Node.EventType.SIZE_CHANGED, transformChangedCallback, this)
  1166. targetNode.off(cc.Node.EventType.ANCHOR_CHANGED, transformChangedCallback, this)
  1167. this.offTargetNodeParentTransformChanged(targetNode, transformChangedCallback)
  1168. }
  1169. this.scheduleOnce(() => {
  1170. targetNode.on(cc.Node.EventType.POSITION_CHANGED, transformChangedCallback, this)
  1171. targetNode.on(cc.Node.EventType.SIZE_CHANGED, transformChangedCallback, this)
  1172. targetNode.on(cc.Node.EventType.ANCHOR_CHANGED, transformChangedCallback, this)
  1173. this.onTargetNodeParentTransformChanged(targetNode, transformChangedCallback)
  1174. }, 0.01)
  1175. // Adjusts the guide text.
  1176. // 调整引导文本。
  1177. this.adjustGuideTextLabelNode(step)
  1178. }
  1179. /**
  1180. * @en
  1181. * The anchor point of target node could be different from that of mask node, so the position should be adjused according to the anchor point.
  1182. * @zh
  1183. * 目标节点的锚点可能可遮罩节点不同,所以需要根据锚点来调整遮罩位置
  1184. */
  1185. adjustPosAccordingToAnchorPoint(nodeToAdjust: cc.Node, nodeToGuide: cc.Node) {
  1186. let nodeToAdjustAnchorPoint = nodeToAdjust.getAnchorPoint()
  1187. let nodeToGuideAnchorPoint = nodeToGuide.getAnchorPoint()
  1188. if (
  1189. nodeToAdjustAnchorPoint.x == nodeToGuideAnchorPoint.x &&
  1190. nodeToAdjustAnchorPoint.y == nodeToGuideAnchorPoint.y
  1191. ) {
  1192. return
  1193. }
  1194. let xDiff = nodeToAdjustAnchorPoint.x - nodeToGuideAnchorPoint.x
  1195. let yDiff = nodeToAdjustAnchorPoint.y - nodeToGuideAnchorPoint.y
  1196. nodeToAdjust.position = nodeToAdjust.position.add(
  1197. new cc.Vec3(xDiff * nodeToGuide.width, yDiff * nodeToGuide.height, 0),
  1198. )
  1199. }
  1200. /**
  1201. * @en
  1202. * Watches the transformation of all parent ndoes.
  1203. * @zh
  1204. * 监听目标节点所有父类的变化。
  1205. */
  1206. onTargetNodeParentTransformChanged(targetNode: cc.Node, posChangedCallback: any) {
  1207. let currentParentNode = null
  1208. while (true) {
  1209. if (!currentParentNode && targetNode.parent) {
  1210. currentParentNode = targetNode.parent
  1211. currentParentNode.on(cc.Node.EventType.POSITION_CHANGED, posChangedCallback, this)
  1212. currentParentNode.on(cc.Node.EventType.SIZE_CHANGED, posChangedCallback, this)
  1213. currentParentNode.on(cc.Node.EventType.ANCHOR_CHANGED, posChangedCallback, this)
  1214. } else if (currentParentNode && currentParentNode.parent) {
  1215. currentParentNode = currentParentNode.parent
  1216. currentParentNode.on(cc.Node.EventType.POSITION_CHANGED, posChangedCallback, this)
  1217. currentParentNode.on(cc.Node.EventType.SIZE_CHANGED, posChangedCallback, this)
  1218. currentParentNode.on(cc.Node.EventType.ANCHOR_CHANGED, posChangedCallback, this)
  1219. } else {
  1220. break
  1221. }
  1222. }
  1223. }
  1224. /**
  1225. * @en
  1226. * Unwatches the transformation of all parent ndoes.
  1227. * @zh
  1228. * 取消监听目标节点所有父类的缓动变化。
  1229. */
  1230. offTargetNodeParentTransformChanged(targetNode: cc.Node, posChangedCallback: any) {
  1231. let currentParentNode = null
  1232. while (true) {
  1233. if (!currentParentNode && targetNode.parent) {
  1234. currentParentNode = targetNode.parent
  1235. currentParentNode.off(cc.Node.EventType.POSITION_CHANGED, posChangedCallback, this)
  1236. currentParentNode.off(cc.Node.EventType.SIZE_CHANGED, posChangedCallback, this)
  1237. currentParentNode.off(cc.Node.EventType.ANCHOR_CHANGED, posChangedCallback, this)
  1238. } else if (currentParentNode && currentParentNode.parent) {
  1239. currentParentNode = currentParentNode.parent
  1240. currentParentNode.off(cc.Node.EventType.POSITION_CHANGED, posChangedCallback, this)
  1241. currentParentNode.off(cc.Node.EventType.SIZE_CHANGED, posChangedCallback, this)
  1242. currentParentNode.off(cc.Node.EventType.ANCHOR_CHANGED, posChangedCallback, this)
  1243. } else {
  1244. break
  1245. }
  1246. }
  1247. }
  1248. /**
  1249. * @en
  1250. * Show guide text and keys to be guided.
  1251. * @zh
  1252. * 显示文本和按键引导。
  1253. */
  1254. showKeyAndTextGuide(keys: Array<string>, step: number, isAuto: boolean, callback: Function = null) {
  1255. // Show related nodes.
  1256. // 显示引导相关节点。
  1257. this.maskNode.active = true
  1258. this.guideTextBgSpriteNode.active = true
  1259. // Sets callback function.
  1260. // 设置回调函数。
  1261. // Last press time.
  1262. // 上次一按键时间。
  1263. let lastKeyDownTime = 0
  1264. // Keys pressed.
  1265. // 按下的键。
  1266. let pressedKeys = []
  1267. let keyDownCallback = event => {
  1268. // If the key-down interval is over 1.5 second, then we are not having combined keys.
  1269. // 如果按键间隔超过1.5秒则说明不是组合键。
  1270. let now = new Date().getTime()
  1271. if ((now - lastKeyDownTime) / 1000 > this.keyDownInterval) {
  1272. lastKeyDownTime = now
  1273. pressedKeys = []
  1274. }
  1275. // Return if it's not the target key.
  1276. // 如果按键不等于引导中的按键,则返回。
  1277. pressedKeys.push(event.keyCode.toString())
  1278. if (JSON.stringify(keys) != JSON.stringify(pressedKeys)) {
  1279. return
  1280. }
  1281. this.hideGuide()
  1282. if (isAuto) {
  1283. this.goToNextGuide(step, isAuto, callback)
  1284. } else if (callback) {
  1285. callback()
  1286. }
  1287. cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, keyDownCallback, this)
  1288. }
  1289. cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, keyDownCallback, this)
  1290. // Sets mask.
  1291. // 设置遮罩。
  1292. this.maskNode.setPosition(new cc.Vec3(0, 0, 0))
  1293. this.maskNode.setSiblingIndex(0)
  1294. this.maskNode.getComponent(cc.Mask).inverted = true
  1295. this.maskNode.width = 0
  1296. this.maskNode.height = 0
  1297. // Adjusts the guide text.
  1298. // 调整引导文本。
  1299. this.adjustGuideTextBgSpriteNode()
  1300. this.adjustGuideTextLabelNode(step)
  1301. }
  1302. /**
  1303. * @en
  1304. * Adjust guide sign node. Different guide sign sprites need different adjustments.
  1305. * @zh
  1306. * 调整引导图片,不同引导图片需要做不同的调整。
  1307. */
  1308. adjustGuideSignSpriteNode(step: number) {
  1309. // Set the sibling index to maximum.
  1310. // 设置层级最大。
  1311. this.guideSignSpriteNode.setSiblingIndex(Number.MAX_SAFE_INTEGER)
  1312. if (this.guideData.guideSignType.includes('frame')) {
  1313. let adjustFunc = () => {
  1314. this.guideSignSpriteNode.angle = this.maskNode.angle
  1315. if (this.guideSignPosTemp) {
  1316. this.guideSignSpriteNode.setPosition(this.guideSignPosTemp)
  1317. } else {
  1318. this.guideSignSpriteNode.setPosition(this.maskNode.position)
  1319. }
  1320. }
  1321. if (this.isGudieSignFlying && step != 1) {
  1322. if (!this.guideSignFlyingTween) {
  1323. this.isFlyingFinised = false
  1324. this.guideSignFlyingTween = cc
  1325. .tween(this.guideSignSpriteNode)
  1326. .to(this.flyingTweenDuration, {
  1327. position: this.maskNode.position,
  1328. rotation: this.guideSignSpriteNode.angle,
  1329. })
  1330. .call(() => {
  1331. adjustFunc()
  1332. this.isFlyingFinised = true
  1333. if (this.isGuideSignTweenEnabled) {
  1334. this.startGuideSignTween()
  1335. }
  1336. })
  1337. this.guideSignFlyingTween.start()
  1338. } else if (this.isFlyingFinised) {
  1339. adjustFunc()
  1340. }
  1341. } else {
  1342. adjustFunc()
  1343. }
  1344. //this.guideSignSpriteNode.width = this.maskNode.width * 1.1
  1345. //this.guideSignSpriteNode.height = this.maskNode.height * 1.1
  1346. }
  1347. if (this.guideData.guideSignType.includes('hand') || this.guideData.guideSignType.includes('arrow')) {
  1348. // If size of the mask hole is 0, then hide the guide sign.
  1349. // 如果遮罩挖洞宽高为0,则隐藏引导图片。
  1350. if (!this.maskNode.width || !this.maskNode.height) {
  1351. //this.guideSignSpriteNode.active = false
  1352. }
  1353. // Adjusts the position and rotation of the guide sign node according to the mask hole.
  1354. // 根据遮罩挖洞位置调整引导图片位置和角度。
  1355. if (this.maskNode.position.y >= 0) {
  1356. let adjustFunc = () => {
  1357. this.guideSignSpriteNode.angle = this.guideSignRotation // 手指朝上
  1358. if (this.guideSignPosTemp) {
  1359. this.guideSignSpriteNode.setPosition(this.guideSignPosTemp)
  1360. } else {
  1361. this.guideSignSpriteNode.setPosition(
  1362. new cc.Vec3(this.maskNode.position).subtract(
  1363. new cc.Vec3(0, this.maskNode.height * 1.01, 0),
  1364. ),
  1365. )
  1366. }
  1367. }
  1368. if (this.isGudieSignFlying && step != 1) {
  1369. if (!this.guideSignFlyingTween) {
  1370. this.isFlyingFinised = false
  1371. this.guideSignFlyingTween = cc
  1372. .tween(this.guideSignSpriteNode)
  1373. .to(this.flyingTweenDuration, {
  1374. position: new cc.Vec3(this.maskNode.position).subtract(
  1375. new cc.Vec3(0, this.maskNode.height * 1.01, 0),
  1376. ),
  1377. rotation: this.guideSignSpriteNode.angle,
  1378. })
  1379. .call(() => {
  1380. adjustFunc()
  1381. this.isFlyingFinised = true
  1382. if (this.isGuideSignTweenEnabled) {
  1383. this.startGuideSignTween()
  1384. }
  1385. })
  1386. this.guideSignFlyingTween.start()
  1387. } else if (this.isFlyingFinised) {
  1388. adjustFunc()
  1389. }
  1390. } else {
  1391. adjustFunc()
  1392. }
  1393. } else if (this.maskNode.position.y < 0) {
  1394. let adjustFunc = () => {
  1395. this.guideSignSpriteNode.angle = this.guideSignRotation // 手指朝下
  1396. if (this.guideSignPosTemp) {
  1397. this.guideSignSpriteNode.setPosition(this.guideSignPosTemp)
  1398. } else {
  1399. this.guideSignSpriteNode.setPosition(
  1400. new cc.Vec3(this.maskNode.position).subtract(
  1401. new cc.Vec3(0, -this.maskNode.height * 1.01, 0),
  1402. ),
  1403. )
  1404. }
  1405. }
  1406. if (this.isGudieSignFlying && step != 1) {
  1407. if (!this.guideSignFlyingTween) {
  1408. this.isFlyingFinised = false
  1409. this.guideSignFlyingTween = cc
  1410. .tween(this.guideSignSpriteNode)
  1411. .to(this.flyingTweenDuration, {
  1412. position: new cc.Vec3(this.maskNode.position).subtract(
  1413. new cc.Vec3(0, -this.maskNode.height * 1.01, 0),
  1414. ),
  1415. rotation: this.guideSignSpriteNode.angle,
  1416. })
  1417. .call(() => {
  1418. adjustFunc()
  1419. this.isFlyingFinised = true
  1420. if (this.isGuideSignTweenEnabled) {
  1421. this.startGuideSignTween()
  1422. }
  1423. })
  1424. this.guideSignFlyingTween.start()
  1425. } else if (this.isFlyingFinised) {
  1426. adjustFunc()
  1427. }
  1428. } else {
  1429. adjustFunc()
  1430. }
  1431. }
  1432. // If the guide sign tween exists, starts it.
  1433. // 如果引导图片缓动存在,则开启。
  1434. if (this.isGuideSignTweenEnabled && this.isFlyingFinised) {
  1435. this.startGuideSignTween()
  1436. }
  1437. }
  1438. }
  1439. /**
  1440. * @en
  1441. * Adjust guide guide text. If there are many words, a bigger text background will be used. If the guide text is put at bottom, guide text background won't need adjustment.
  1442. * @zh
  1443. * 调整文本背景图片大小和位置。如果文本很多那图片就要大些,如果是放在底部的则无需调整。
  1444. */
  1445. adjustGuideTextBgSpriteNode() {
  1446. // Sets the sibling index to maximum.
  1447. // 设置层级最大
  1448. this.guideTextBgSpriteNode.setSiblingIndex(Number.MAX_SAFE_INTEGER)
  1449. // The guide text will be shown at center.
  1450. // 屏幕居中显示。
  1451. if (this.textPosTemp == 'center') {
  1452. // Adjusts the background's size.
  1453. // 调整文本背景大小。
  1454. this.setGuideTextBgSpriteSizeByTextLength()
  1455. // Adjusts the guide text backrgound's position.
  1456. // 调整文本背景位置。
  1457. this.guideTextBgSpriteNode.setPosition(0, 0, 0)
  1458. }
  1459. // The guide text will be shown at bottom.
  1460. // 屏幕底部显示。
  1461. else if (this.textPosTemp == 'bottom') {
  1462. // Adjusts the guide text background's size.
  1463. // 调整文本背景大小。
  1464. this.setGuideTextBgSpriteSizeByCanvasSize()
  1465. // Adjusts the guide text backrgound's position.
  1466. // 调整文本背景位置。
  1467. let y = this.canvasUITransform.height / 2 - this.guideTextBgSpriteNode.height / 2
  1468. this.guideTextBgSpriteNode.setPosition(0, -y, 0)
  1469. }
  1470. // The guide text will be shown next to the target node.
  1471. // 跟随引导图片显示。
  1472. else if (this.textPosTemp == 'follow') {
  1473. // Adjusts the background's size.
  1474. // 调整文本背景大小。
  1475. this.setGuideTextBgSpriteSizeByTextLength()
  1476. // Adjusts the guide text backrgound's position.
  1477. // 调整文本背景位置。
  1478. if (this.maskNode.position.x >= 0 && this.maskNode.position.y >= 0) {
  1479. this.guideTextBgSpriteNode.setPosition(
  1480. new cc.Vec3(this.maskNode.position).subtract(
  1481. new cc.Vec3(this.maskNode.width * 1.1, this.maskNode.height * 1.1, 0),
  1482. ),
  1483. )
  1484. } else if (this.maskNode.position.x >= 0 && this.maskNode.position.y <= 0) {
  1485. this.guideTextBgSpriteNode.setPosition(
  1486. new cc.Vec3(this.maskNode.position).subtract(
  1487. new cc.Vec3(this.maskNode.width * 1.1, -this.maskNode.height * 1.1, 0),
  1488. ),
  1489. )
  1490. } else if (this.maskNode.position.x <= 0 && this.maskNode.position.y >= 0) {
  1491. this.guideTextBgSpriteNode.setPosition(
  1492. new cc.Vec3(this.maskNode.position).subtract(
  1493. new cc.Vec3(-this.maskNode.width * 1.1, this.maskNode.height * 1.1, 0),
  1494. ),
  1495. )
  1496. } else if (this.maskNode.position.x <= 0 && this.maskNode.position.y <= 0) {
  1497. this.guideTextBgSpriteNode.setPosition(
  1498. new cc.Vec3(this.maskNode.position).subtract(
  1499. new cc.Vec3(-this.maskNode.width * 1.1, -this.maskNode.height * 1.1, 0),
  1500. ),
  1501. )
  1502. }
  1503. } else if (typeof this.textPosTemp == 'object') {
  1504. // Adjusts the background's size.
  1505. // 调整文本背景大小。
  1506. this.setGuideTextBgSpriteSizeByTextLength()
  1507. // Adjusts the guide text backrgound's position.
  1508. // 调整文本背景位置。
  1509. this.guideTextBgSpriteNode.setPosition(this.textPosTemp)
  1510. let offsetX = 120
  1511. let offsetY = -80
  1512. this.roleNode.setPosition(
  1513. this.textPosTemp.add(
  1514. cc.v3(
  1515. -this.guideTextBgSpriteNode.width / 2 + offsetX,
  1516. this.guideTextBgSpriteNode.height / 2 + offsetY,
  1517. 0,
  1518. ),
  1519. ),
  1520. )
  1521. }
  1522. }
  1523. /**
  1524. * @en
  1525. * When the guide text is shown at bottom, its size is adjusted based on the canvas size.
  1526. * @zh
  1527. * 当引导文本显示在屏幕底部时,根据屏幕大小来设置文本背景大小。
  1528. */
  1529. setGuideTextBgSpriteSizeByCanvasSize() {
  1530. this.guideTextBgSpriteNode.width = this.canvasUITransform.width
  1531. this.guideTextBgSpriteNode.height = this.canvasUITransform.height / 7
  1532. }
  1533. /**
  1534. * @en
  1535. * When the guide text is shown next to target node or at center, its size is adjusted based on the text length.
  1536. * @zh
  1537. * 当引导文本跟随引导图片或居中显示时,根据引导文本长度调整文本背景大小。
  1538. */
  1539. setGuideTextBgSpriteSizeByTextLength() {
  1540. let guideText = ''
  1541. let width = 0
  1542. let height = 0
  1543. if (Mgr.i18n.getLanguage() == 'zh') {
  1544. guideText = this.guideData.nodesAndTexts[this.currentStepTemp - 1].guideText
  1545. if (guideText.length <= 15 && guideText.length > 0) {
  1546. width = this.canvasUITransform.width / 5
  1547. height = this.canvasUITransform.height / 10
  1548. } else if (guideText.length > 15 && guideText.length <= 40) {
  1549. width = this.canvasUITransform.width / 5
  1550. height = this.canvasUITransform.height / 8
  1551. } else if (guideText.length > 40) {
  1552. width = this.canvasUITransform.width / 3
  1553. height = this.canvasUITransform.height / 6
  1554. }
  1555. } else {
  1556. guideText = this.guideData.nodesAndTexts[this.currentStepTemp - 1].guideText
  1557. if (guideText.length <= 40 && guideText.length > 0) {
  1558. width = this.canvasUITransform.width / 3
  1559. height = this.canvasUITransform.height / 10
  1560. } else if (guideText.length > 15 && guideText.length <= 80) {
  1561. width = this.canvasUITransform.width / 3
  1562. height = this.canvasUITransform.height / 8
  1563. } else if (guideText.length > 80) {
  1564. width = this.canvasUITransform.width / 2
  1565. height = this.canvasUITransform.height / 6
  1566. }
  1567. }
  1568. width = 820
  1569. height = 210
  1570. if (!this.roleNode.active) {
  1571. width = 540
  1572. height = 160
  1573. }
  1574. // Switch the value of width and height if the canvas direction is portrait.
  1575. // 如果是竖屏则将width和height值对调。
  1576. if (width < height) {
  1577. let temp = height
  1578. height = width
  1579. width = temp
  1580. }
  1581. this.guideTextBgSpriteNode.width = width
  1582. this.guideTextBgSpriteNode.height = height
  1583. }
  1584. /**
  1585. * @en
  1586. * Sets guide text and adjusts the label size according to the background node.
  1587. * @zh
  1588. * 设置引导文本并根据文本背景图片调整Label宽高以及字体大小。
  1589. */
  1590. adjustGuideTextLabelNode(step: number) {
  1591. if (!this.isTyping) {
  1592. // If typing effect is not enabled, set the text directly to Label.
  1593. // 如果没有打字机效果,则直接将引导文本设置到Label上。
  1594. if (this.guideTextLang == 'zh') {
  1595. this.guideTextLabelNode.getComponent(cc.Label).string = this.guideData.nodesAndTexts[step - 1].guideText
  1596. } else {
  1597. this.guideTextLabelNode.getComponent(cc.Label).string = this.guideData.nodesAndTexts[
  1598. step - 1
  1599. ].guideEnText
  1600. }
  1601. } else {
  1602. this.scheduleCount = 0
  1603. if (this.guideTextLang == 'zh') {
  1604. this.guideTextTemp = this.guideData.nodesAndTexts[step - 1].guideText
  1605. } else {
  1606. this.guideTextTemp = this.guideData.nodesAndTexts[step - 1].guideEnText
  1607. }
  1608. // Sets the callback function.
  1609. // 设置调度函数。
  1610. let callback = () => {
  1611. if (this.guideTextTemp[this.scheduleCount]) {
  1612. this.guideTextLabelNode.getComponent(cc.Label).string += this.guideTextTemp[this.scheduleCount]
  1613. }
  1614. this.scheduleCount++
  1615. if (this.scheduleCount >= this.guideTextTemp.length) {
  1616. this.unschedule(callback)
  1617. }
  1618. }
  1619. // Cancel the last schedule and clean the text content.
  1620. // 开始调度前要先取消上一次的调度并清空文本。
  1621. this.unschedule(callback)
  1622. this.guideTextLabelNode.getComponent(cc.Label).string = ''
  1623. // Begins a new schedule.
  1624. // 开始新的调度。
  1625. this.schedule(callback, this.typingInterval)
  1626. }
  1627. // The size of Label should be a little bit smaller than that of the text background node.
  1628. // Label大小稍微比背景图片小点。
  1629. this.guideTextLabelNode.width = (this.guideTextBgSpriteNode.width * this.guideTextBgSpriteNode.scaleX) / 1.1
  1630. this.guideTextLabelNode.height = (this.guideTextBgSpriteNode.height * this.guideTextBgSpriteNode.scaleY) / 1.1
  1631. }
  1632. /**
  1633. * @en
  1634. * Find the target node recursively.
  1635. * @zh
  1636. * 递归寻找目标节点。
  1637. */
  1638. getNodeByUuid(node: cc.Node, uuid: string) {
  1639. let targetNode = null
  1640. for (let i = 0; i < node.children.length; i++) {
  1641. if (node.children[i].uuid == uuid) {
  1642. targetNode = node.children[i]
  1643. break
  1644. } else if (node.children[i].children.length) {
  1645. targetNode = this.getNodeByUuid(node.children[i], uuid)
  1646. if (targetNode) {
  1647. break
  1648. }
  1649. }
  1650. }
  1651. return targetNode
  1652. }
  1653. /**
  1654. * @en
  1655. * Get positions of all parent nodes except for Canvas.
  1656. * @zh
  1657. * 获取目标节点坐标及其所有父节点,祖父节点,曾祖父节点...的坐标(不包括Canvas节点)。
  1658. */
  1659. getAllParentPosIncludingSelf(node: cc.Node) {
  1660. let posArray = [node.position]
  1661. let tempNode = node
  1662. while (true) {
  1663. let parentNode = tempNode.parent
  1664. if (parentNode && parentNode != this.node) {
  1665. posArray.push(parentNode.position)
  1666. tempNode = parentNode
  1667. } else {
  1668. break
  1669. }
  1670. }
  1671. return posArray
  1672. }
  1673. }