BobbleGamePanel.ts 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571
  1. /**
  2. * 代码描述
  3. */
  4. import { Audio } from "../../common/src/Audio";
  5. import { GameDataCenter } from "../../common/src/GameDataCenter";
  6. import { LevelConfig } from "../../common/src/LevelConfig";
  7. import { UIManager } from "../../common/src/UIManager";
  8. import { Utils } from "../../common/src/Utils";
  9. const { ccclass, property } = cc._decorator;
  10. @ccclass
  11. export class BobbleGamePanel extends cc.Component {
  12. @property({ type: cc.Node, tooltip: '反弹界面节点' })
  13. walls: cc.Node = null;
  14. @property({ type: cc.Graphics, tooltip: '射线节点' })
  15. ray: cc.Graphics = null;
  16. @property({ type: cc.Node, tooltip: '地图节点' })
  17. map: cc.Node = null;
  18. @property({ type: cc.Node, tooltip: '角色节点' })
  19. player: cc.Node = null;
  20. @property({ type: cc.Node, tooltip: 'ui节点' })
  21. ui: cc.Node = null;
  22. @property({ type: cc.Prefab, tooltip: '泡泡预制体' })
  23. bubble: cc.Prefab = null;
  24. @property({ type: cc.Prefab, tooltip: '射线预制体' })
  25. rayPrefab: cc.Prefab = null;
  26. @property({ type: cc.Prefab, tooltip: '激励预制体' })
  27. appraisePrefab: cc.Prefab = null;
  28. @property({ type: cc.Prefab, tooltip: '发射小球预制体' })
  29. shootBubblePre: cc.Prefab = null;
  30. @property({ type: cc.Prefab, tooltip: '激光预制体' })
  31. laser_gj: cc.Prefab = null;
  32. @property({ type: cc.Prefab, tooltip: '闪电预制体' })
  33. thunder_gj: cc.Prefab = null;
  34. @property({ type: cc.Prefab, tooltip: '总分预制体' })
  35. scorePrefab: cc.Prefab = null;
  36. @property({ type: cc.Prefab, tooltip: '箭头预制体' })
  37. arrows: cc.Prefab = null;
  38. @property({ type: [cc.SpriteFrame], tooltip: '普通泡泡纹理集合\n0.紫色\n1.绿色\n2.蓝色\n3.黄色\n4.红色' })
  39. bubbleSpriteFrame: cc.SpriteFrame[] = [];
  40. @property({ type: [cc.SpriteFrame], tooltip: '特殊泡泡纹理集合\n0.炸弹\n1.激光\n2.七色\n3.闪电' })
  41. specialBubbleSpriteFrame: cc.SpriteFrame[] = [];
  42. @property({ type: [cc.SpriteFrame], tooltip: '图标集合\n0.广告\n1.无限\n2.金币\n3.暗星\n4.亮星' })
  43. iconSpriteFrame: cc.SpriteFrame[] = [];
  44. @property({ type: [cc.Prefab], tooltip: '特殊球待机动画预制体\n0.炸弹\n1.激光\n2.七色\n3.闪电' })
  45. specialBubbleEffect: cc.Prefab[] = [];
  46. //线段颜色
  47. private rayColor: cc.Color[] = [cc.color('#a600e6' as any), cc.color('#0ca600' as any), cc.color('#10c8e3' as any), cc.color('#f77916' as any), cc.color('#cd1904' as any)];
  48. /**特殊球颜色 */
  49. private specialColor: cc.Color[][] = [[cc.color('#fdce25' as any), cc.color('#f48118' as any), cc.color('#f48118' as any), cc.color('#fdce25' as any)], [cc.color('#f0e288' as any), cc.color('#d999d1' as any), cc.color('#92e7fc' as any)], [cc.color('#48adf7' as any), cc.color('#fdde52' as any), cc.color('#f77923' as any), cc.color('#d7008e' as any)], [cc.color('#073dd3' as any), cc.color('#ffffff' as any), cc.color('#073dd3' as any)]];
  50. /**总分评价 */
  51. private appraise: string[] = ['bksy', 'tbl', 'bc'];
  52. //发射坐标
  53. private startPos: cc.Vec2 = cc.v2();
  54. //射线节点坐标
  55. private rayPos: cc.Vec2[] = [];
  56. private pathPos: cc.Vec2[] = [];
  57. //射线节点半径
  58. private r: number = 0;
  59. //放大缩小方向
  60. private op: number = 1;
  61. //是否隐藏
  62. private isHide: boolean = true;
  63. //泡泡半径
  64. private bubbleR: number = 30;
  65. //地图高度
  66. private screenH: number = 0;
  67. //地图宽度
  68. private screenW: number = 0;
  69. /** 当前发射小球 */
  70. public shootBubble: cc.Node;
  71. /** 预发射小球 */
  72. public preBubble: cc.Node;
  73. /** 特殊小球 */
  74. public specialBubble: cc.Node;
  75. /**校正之后泡泡的位置 */
  76. private bubbleIndex: cc.Vec2 = null;
  77. /**小球数量 */
  78. private bubbleCount: number = 0;
  79. /**连击数 */
  80. private combo: number = 0;
  81. /**是否在准备泡泡 */
  82. private isReady: boolean = false;
  83. /**场上小球的颜色数量 */
  84. private colorCount: number[] = [0, 0, 0, 0, 0, 0];
  85. /**特殊球类型 */
  86. private specialBubbleType: number = 0;
  87. /**特殊球消除位置 */
  88. private specialBubbleIndex: cc.Vec2[] = [];
  89. /**激光终点向量 */
  90. private laserVec: cc.Vec2 = null;
  91. /**闪电爆炸位置 */
  92. private thunderIndex: cc.Vec2 = null;
  93. /**游戏是否结束 */
  94. private isWin: boolean = false;
  95. /**得分 */
  96. private score: number = 0;
  97. /**三星分数 */
  98. private perfectScore: number = 0;
  99. /**星星数 */
  100. private star: number = 0;
  101. /**首次出现冰球的关卡 */
  102. private iceTips: number = 31;
  103. /**在线时间 */
  104. private onlineTime: number = 0;
  105. /*要显示的排数*/
  106. private showCount: number = 10;
  107. private callBack: Function = null;
  108. private isPress: boolean = false;
  109. onLoad() {
  110. Audio.playMusicByPath('game:res/snd/bgm');
  111. cc.director.getPhysicsManager().enabled = true;
  112. }
  113. onEnable() {
  114. this.scheduleOnce(() => {
  115. this.init();
  116. }, 0.5);
  117. let specialBubble = this.ui.getChildByName('specialBubble');
  118. for (let i = 0; i < specialBubble.childrenCount; i++) {
  119. specialBubble.children[i].on('click', this.onSpecialBubble, this);
  120. }
  121. this.player.getChildByName('icon').on('click', this.onSwitchBubble, this)
  122. this.ui.getChildByName('cancel').on('click', this.onCancel, this);
  123. this.ui.getChildByName('topPanel').getChildByName('pauseButton').on('click', this.onPause, this);
  124. this.ui.getChildByName('topPanel').getChildByName('coin').getChildByName('addButton').on('click', this.onCoinStore, this);
  125. this.ui.getChildByName('online').on('click', this.onOnline, this);
  126. this.ui.getChildByName('ten').on('click', () => {
  127. cc.systemEvent.emit('updateBubble', 10);
  128. }, this);
  129. cc.systemEvent.on('restart', this.onRestart, this);
  130. cc.systemEvent.on('updateBubble', this.onUpdateBubble, this);
  131. cc.systemEvent.on('updateUI', this.onUpdateUI, this);
  132. cc.systemEvent.on('startTimer', this.onStartTimer, this);
  133. cc.systemEvent.on('showTenButton', (isShow: boolean) => { this.ui.getChildByName('ten').active = isShow }, this);
  134. this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
  135. this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMoved, this);
  136. this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnded, this);
  137. this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancelled, this);
  138. }
  139. onDisable() {
  140. this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
  141. this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMoved, this);
  142. this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchEnded, this);
  143. this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancelled, this);
  144. }
  145. /**点击特殊球 */
  146. private onSpecialBubble(button): void {
  147. if (GameDataCenter.gameLevel == 12) {
  148. this.ui.getChildByName('colorTip').active = false;
  149. GameDataCenter.tipType = 2;
  150. UIManager.open('tip:TipPanel');
  151. }
  152. if (!this.isReady || this.isWin) return;
  153. this.isPress = true;
  154. Audio.playSoundByPath('game:res/snd/click');
  155. if (button.node.getChildByName('null').active == true && GameDataCenter.coin < 100) {
  156. switch (button.node.name) {
  157. case 'bombBubble': this.specialBubbleCallback(1); break;
  158. case 'laserBubble': this.specialBubbleCallback(2); break;
  159. case 'omnipotentBubble': this.specialBubbleCallback(3); break;
  160. case 'lightningBubble': this.specialBubbleCallback(4); break;
  161. }
  162. return;
  163. }
  164. switch (button.node.name) {
  165. case 'bombBubble': this.specialBubbleType = 1; break;
  166. case 'laserBubble': this.specialBubbleType = 2; break;
  167. case 'omnipotentBubble': this.specialBubbleType = 3; break;
  168. case 'lightningBubble': this.specialBubbleType = 4; break;
  169. }
  170. this.player.getChildByName('icon').active = false;
  171. let specialBubble = this.ui.getChildByName('specialBubble');
  172. for (let i = 0; i < specialBubble.childrenCount; i++) {
  173. specialBubble.children[i].getComponent(cc.Button).interactable = false;
  174. }
  175. this.switchSpecialBubble(1);
  176. }
  177. /**点击取消 */
  178. private onCancel(): void {
  179. Audio.playSoundByPath('game:res/snd/click');
  180. this.specialBubbleType = 0;
  181. this.switchSpecialBubble(-1);
  182. this.isPress = false;
  183. }
  184. /**暂停界面 */
  185. private onPause(): void {
  186. Audio.playSoundByPath('game:res/snd/click');
  187. UIManager.open('pause:PausePanel');
  188. }
  189. /**金币商店 */
  190. private onCoinStore(): void {
  191. Audio.playSoundByPath('game:res/snd/click');
  192. UIManager.open('coinStore:CoinStorePanel');
  193. }
  194. /**点击切换小球 */
  195. private onSwitchBubble(button): void {
  196. if (!this.isReady || this.isWin) return;
  197. Audio.playSoundByPath('game:res/snd/click');
  198. this.isReady = false;
  199. button.node.getComponent(cc.Button).interactable = false;
  200. if (button.node.children[0].name == '0') {
  201. this.callBack = () => {
  202. button.node.children[0].getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[1];
  203. button.node.children[0].name = '1';
  204. let pos = this.player.convertToNodeSpaceAR(this.startPos);
  205. cc.tween(this.shootBubble).to(0.2, { position: cc.v3(pos.x + 60, pos.y - 60), scale: 0.75 }).start();
  206. cc.tween(this.preBubble).to(0.2, { position: cc.v3(pos.x, pos.y), scale: 1 }).call(() => {
  207. let node: cc.Node = null;
  208. node = this.shootBubble;
  209. this.shootBubble = this.preBubble;
  210. this.preBubble = node;
  211. this.scheduleOnce(() => {
  212. this.isReady = true;
  213. }, 0);
  214. this.ray.fillColor = this.rayColor[this.shootBubble.getComponent('Bubble').color - 1];
  215. button.node.getComponent(cc.Button).interactable = true;
  216. }).start();
  217. }
  218. this.scheduleOnce(() => {
  219. button.node.getComponent(cc.Button).interactable = true;
  220. this.isReady = true;
  221. this.callBack();
  222. }, 1);
  223. return;
  224. }
  225. let pos = this.player.convertToNodeSpaceAR(this.startPos);
  226. cc.tween(this.shootBubble).to(0.2, { position: cc.v3(pos.x + 60, pos.y - 60), scale: 0.75 }).start();
  227. cc.tween(this.preBubble).to(0.2, { position: cc.v3(pos.x, pos.y), scale: 1 }).call(() => {
  228. let node: cc.Node = null;
  229. node = this.shootBubble;
  230. this.shootBubble = this.preBubble;
  231. this.preBubble = node;
  232. this.scheduleOnce(() => {
  233. this.isReady = true;
  234. }, 0);
  235. this.ray.fillColor = this.rayColor[this.shootBubble.getComponent('Bubble').color - 1];
  236. button.node.getComponent(cc.Button).interactable = true;
  237. }).start();
  238. }
  239. /**在线奖励面板 */
  240. private onOnline(): void {
  241. Audio.playSoundByPath('game:res/snd/click');
  242. if (this.onlineTime > 0) {
  243. this.creatLabel(`再多玩一会吧,在线时间还不够哦~`);
  244. return;
  245. }
  246. else {
  247. GameDataCenter.rewarded = [`${Math.floor(Math.random() * 4)}:1`, '4:80'];
  248. UIManager.open('rewarded:RewardedPanel');
  249. cc.systemEvent.emit('startTimer');
  250. }
  251. }
  252. /**再来一次 */
  253. private onRestart(): void {
  254. this.isReady = false;
  255. this.initMap(true);
  256. }
  257. /**更新泡泡数量 */
  258. private onUpdateBubble(num: number): void {
  259. this.isReady = false;
  260. let count: number = this.bubbleCount;
  261. this.bubbleCount += num;
  262. for (let i = 0; i < num; i++) {
  263. this.scheduleOnce(() => {
  264. count++;
  265. this.player.getChildByName('bubbleCount').getComponent(cc.Label).string = `${count}`
  266. }, i * 0.1);
  267. }
  268. this.scheduleOnce(() => {
  269. this.isReady = true;
  270. }, 0.5);
  271. }
  272. /**更新UI数量 */
  273. private onUpdateUI(type: string, num: number) {
  274. this.changeUi(type, num);
  275. }
  276. /**开始在线奖励倒计时 */
  277. private onStartTimer(): void {
  278. let node = this.ui.getChildByName('online').getChildByName('gift');
  279. cc.Tween.stopAllByTarget(node);
  280. node.scale = 1;
  281. node.angle = 0;
  282. this.onlineTime = 120;
  283. this.ui.getChildByName('online').getChildByName('time').getComponent(cc.Label).string = '02;00';
  284. this.ui.getChildByName('online').getChildByName('time').active = true;
  285. this.ui.getChildByName('online').getChildByName('name').getChildByName('label').getComponent(cc.Label).string = `在线奖励`;
  286. this.ui.getChildByName('online').getChildByName('name').getChildByName('label').x -= 14;
  287. this.ui.getChildByName('online').getChildByName('name').getChildByName('videoIcon').active = false;
  288. // this.ui.getChildByName('online').getComponent(cc.Button).interactable = false;
  289. this.schedule(this.online, 1);
  290. }
  291. private specialBubbleCallback(type) {
  292. this.specialBubbleType = type;
  293. this.player.getChildByName('icon').active = false;
  294. let specialBubble = this.ui.getChildByName('specialBubble');
  295. for (let i = 0; i < specialBubble.childrenCount; i++) {
  296. specialBubble.children[i].getComponent(cc.Button).interactable = false;
  297. }
  298. this.switchSpecialBubble(1);
  299. this.changeUi(`special${this.specialBubbleType}`, 1);
  300. }
  301. /**
  302. * 场景动画更新前回调
  303. * @param dt 游戏帧时长
  304. */
  305. update(dt: number) {
  306. if (!this.isHide) {
  307. this.updateRay(dt);
  308. }
  309. }
  310. /** touch事件回调 */
  311. onTouchStart(event: cc.Event.EventTouch) {
  312. this.isPress = true;
  313. if (GameDataCenter.gameLevel == 1) {
  314. if (this.ui.getChildByName('tip').getChildByName('tip1').activeInHierarchy == true) {
  315. cc.Tween.stopAllByTarget(this.ui.getChildByName('tip').getChildByName('tip1').getChildByName('finger'));
  316. this.ui.getChildByName('tip').getChildByName('tip1').active = false;
  317. }
  318. }
  319. if (GameDataCenter.gameLevel == 2) {
  320. if (this.ui.getChildByName('tip').getChildByName('tip3').activeInHierarchy == true) {
  321. this.ui.getChildByName('tip').getChildByName('tip3').active = false;
  322. this.node.getChildByName('effect').removeAllChildren();
  323. }
  324. }
  325. // if (GameDataCenter.gameLevel == 11) {
  326. // if (this.ui.getChildByName('tip').getChildByName('tip4').activeInHierarchy == true) {
  327. // this.ui.getChildByName('tip').getChildByName('tip4').active = false;
  328. // }
  329. // }
  330. if (!this.isReadyRay(event)) { return; }
  331. this.topTween(0);
  332. this.rayPos = [];
  333. this.pathPos = [this.ray.node.convertToNodeSpaceAR(this.startPos)];
  334. const pos = event.getLocation();
  335. this.drawRayCast(this.startPos, pos.subSelf(this.startPos).normalizeSelf(), this.ray);
  336. }
  337. onTouchMoved(event: cc.Event.EventTouch) {
  338. if (!this.isReadyRay(event)) { return; }
  339. this.topTween(0);
  340. this.rayPos = [];
  341. this.pathPos = [this.ray.node.convertToNodeSpaceAR(this.startPos)];
  342. const pos = event.getLocation();
  343. this.drawRayCast(this.startPos, pos.subSelf(this.startPos).normalizeSelf(), this.ray);
  344. }
  345. onTouchEnded(event: cc.Event.EventTouch) {
  346. this.isPress = false;
  347. if (this.isHide) { return; }
  348. this.topTween(1);
  349. this.ray.clear();
  350. for (let i = 0; i < this.ray.node.childrenCount; i++) {
  351. this.ray.node.children[i].getComponent(cc.Graphics).clear();
  352. }
  353. this.isReady = false;
  354. this.laserVec = event.getLocation();
  355. this.shootBubble.getChildByName('trailing_normal').active = true;
  356. switch (this.specialBubbleType) {
  357. case 0:
  358. Audio.playSoundByPath('game:res/snd/shoot');
  359. break;
  360. case 1:
  361. Audio.playSoundByPath('game:res/snd/bomb');
  362. break;
  363. case 2:
  364. Audio.playSoundByPath('game:res/snd/laser');
  365. break;
  366. case 3:
  367. Audio.playSoundByPath('game:res/snd/omnipotent');
  368. break;
  369. case 4:
  370. Audio.playSoundByPath('game:res/snd/lightning');
  371. break;
  372. }
  373. this.ui.getChildByName('cancel').active = false;
  374. this.bubbleMove(1);
  375. this.isHide = true;
  376. }
  377. onTouchCancelled(event: cc.Event.EventTouch) {
  378. this.isPress = false;
  379. this.ray.clear();
  380. for (let i = 0; i < this.ray.node.childrenCount; i++) {
  381. this.ray.node.children[i].getComponent(cc.Graphics).clear();
  382. }
  383. this.isHide = true;
  384. }
  385. /**初始化 */
  386. private init(): void {
  387. if (!GameDataCenter.isInitSpecial) {
  388. GameDataCenter.isInitSpecial = true;
  389. cc.systemEvent.emit('updateUI', 'special1', 1);
  390. cc.systemEvent.emit('updateUI', 'special2', 1);
  391. cc.systemEvent.emit('updateUI', 'special3', 1);
  392. cc.systemEvent.emit('updateUI', 'special4', 1);
  393. }
  394. if (GameDataCenter.gameLevel >= 8) {
  395. //签到
  396. if (!GameDataCenter.isSignIn) {
  397. this.scheduleOnce(() => {
  398. UIManager.open('attendance:AttendancePanel');
  399. }, 0.1)
  400. }
  401. }
  402. //初始化ui
  403. this.onStartTimer();
  404. this.changeUi('coin');
  405. this.changeUi('special0');
  406. this.changeUi('ingot');
  407. //初始化初始发射点
  408. this.startPos = this.node.convertToWorldSpaceAR(cc.v2(this.player.position.x, this.player.position.y));
  409. //初始化泡泡半径
  410. this.bubbleR = Math.floor(this.node.getContentSize().width / 11 / 2);
  411. //初始化地图宽度
  412. this.screenW = this.node.getContentSize().width;
  413. //设置地图大小
  414. // this.map.setContentSize(this.screenW, this.node.getContentSize().height * 3 / 7);
  415. //初始化地图高度
  416. this.screenH = this.map.getContentSize().height;
  417. //初始化地图
  418. this.scheduleOnce(() => {
  419. this.createShootBubble(true);
  420. this.createShootBubble();
  421. this.initMap(true);
  422. }, 0.5);
  423. }
  424. /**初始化地图 */
  425. private initMap(isInit: boolean = false): void {
  426. this.ui.getChildByName('ten').active = false;
  427. GameDataCenter.bubbles = [];
  428. this.map.removeAllChildren();
  429. //初始化广告图片
  430. let icon = this.player.getChildByName('icon');
  431. icon.zIndex = 100;
  432. icon.children[0].getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[0];
  433. icon.children[0].name = '0';
  434. this.colorCount = [0, 0, 0, 0, 0, 0];
  435. this.specialBubbleType = 0;
  436. this.combo = 0;
  437. this.star = 0;
  438. this.isWin = false;
  439. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('levelLabel').getComponent(cc.Label).string = `第${GameDataCenter.gameLevel}关`
  440. this.map.position = cc.v3(0, -this.node.getContentSize().height);
  441. this.walls.getChildByName('top').position = this.walls.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(cc.v3(this.map.position.x, this.map.getContentSize().height + this.walls.getChildByName('top').getContentSize().height / 2)));
  442. let length = Object.keys(LevelConfig.level).length;
  443. let gameLevel = LevelConfig.level[GameDataCenter.gameLevel > length ? Math.floor(Math.random() * length) + 1 : GameDataCenter.gameLevel]
  444. let bubbleCount = this.bubbleCount;
  445. let count = 0;
  446. this.bubbleCount = isInit ? gameLevel.bubbleCount : gameLevel.bubbleCount + 1;
  447. for (let i = 0; i < Math.max(gameLevel.bubbleCount - bubbleCount, 0); i++) {
  448. this.scheduleOnce(() => {
  449. bubbleCount++;
  450. this.player.getChildByName('bubbleCount').getComponent(cc.Label).string = `${bubbleCount}`
  451. }, i * 0.05);
  452. }
  453. let data = gameLevel.map;
  454. let time: number = 0;
  455. for (let i = 0; i < data.length; i++) {
  456. GameDataCenter.bubbles[i] = [];
  457. for (let j = 0; j < data[i].length; j++) {
  458. let type = data[i][j];
  459. if (type == 0) continue;
  460. this.scheduleOnce(() => {
  461. this.creatBubble(i, j, type);
  462. count++;
  463. }, time * 0.01);
  464. time = (time++) / 5;
  465. }
  466. }
  467. this.scheduleOnce(() => {
  468. this.changeUi('score', 0);
  469. this.perfectScore = count * 40;
  470. GameDataCenter.bubbles[data.length] = [];
  471. let t = ((1.5 * this.node.getContentSize().height - 210) / (this.bubbleR * Math.sqrt(3))) + Math.max(GameDataCenter.bubbles.length - 10, 0)
  472. this.setMapPosition(t);
  473. this.scheduleOnce(() => {
  474. if (GameDataCenter.gameLevel == 2) {
  475. this.ui.getChildByName('tip').getChildByName('tip3').active = true;
  476. Utils.openPanel(this.ui.getChildByName('tip').getChildByName('tip3'));
  477. this.rayPos = [];
  478. this.drawRayCast(this.startPos, cc.v2(this.startPos.x - 100, this.startPos.y + 140).subSelf(this.startPos).normalizeSelf(), this.ray);
  479. let rayPos = this.rayPos;
  480. for (let i = 0; i < rayPos.length - 2; i++) {
  481. let node = cc.instantiate(this.arrows);
  482. let angle = this.vectorsToDegree(rayPos[i], rayPos[i + 1]);
  483. if (angle != this.vectorsToDegree(rayPos[i + 1], rayPos[i + 2])) {
  484. cc.tween(node)
  485. .to(0.5, { opacity: 0 })
  486. .call(() => {
  487. node.opacity = 255;
  488. })
  489. .union()
  490. .repeatForever()
  491. .start();
  492. }
  493. if (i == rayPos.length - 3) {
  494. cc.tween(node)
  495. .to(0.5, { opacity: 0 })
  496. .call(() => {
  497. node.opacity = 255;
  498. })
  499. .union()
  500. .repeatForever()
  501. .start();
  502. }
  503. node.parent = this.node.getChildByName('effect');
  504. node.position = cc.v3(rayPos[i].x, rayPos[i].y);
  505. node.angle += angle;
  506. cc.tween(node)
  507. .to(0.5, { position: cc.v3(rayPos[i + 1].x, rayPos[i + 1].y) })
  508. .call(() => {
  509. node.position = cc.v3(rayPos[i].x, rayPos[i].y);
  510. })
  511. .union()
  512. .repeatForever()
  513. .start();
  514. }
  515. }
  516. this.switchShootBubble();
  517. }, 0.03 * t + 0.1);
  518. if (GameDataCenter.gameLevel == 1) {
  519. this.ui.getChildByName('tip').getChildByName('tip1').active = true;
  520. cc.tween(this.ui.getChildByName('tip').getChildByName('tip1').getChildByName('finger'))
  521. .by(0.3, { x: -100 })
  522. .by(0.6, { x: 200 })
  523. .by(0.3, { x: -100 })
  524. .union()
  525. .repeatForever()
  526. .start();
  527. }
  528. if (GameDataCenter.gameLevel >= 3) {
  529. this.ui.getChildByName('specialBubble').active = true;
  530. }
  531. if (GameDataCenter.gameLevel >= 8) {
  532. //签到
  533. if (!GameDataCenter.isSignIn && GameDataCenter.gameLevel < 16) {
  534. this.scheduleOnce(() => {
  535. UIManager.open('attendance:AttendancePanel');
  536. }, 0.1);
  537. }
  538. }
  539. // if (GameDataCenter.gameLevel == 11) {
  540. // this.ui.getChildByName('tip').getChildByName('tip4').active = true;
  541. // }
  542. if (GameDataCenter.gameLevel == 12) {
  543. this.ui.getChildByName('colorTip').active = true;
  544. cc.systemEvent.emit('updateUI', `special3`, 1);
  545. }
  546. if (GameDataCenter.gameLevel == 13) {
  547. if (this.onlineTime == 0) {
  548. this.onOnline();
  549. }
  550. }
  551. if (GameDataCenter.gameLevel == this.iceTips || GameDataCenter.gameLevel == 11) {
  552. GameDataCenter.tipType = 2;
  553. UIManager.open('tip:TipPanel');
  554. }
  555. }, time * 0.01 + 1);
  556. }
  557. /**判断射线出现 */
  558. private isReadyRay(event): boolean {
  559. let pos = this.player.parent.convertToNodeSpaceAR(event.getLocation());
  560. if (pos.y < Math.tan(cc.misc.degreesToRadians(20)) * (Math.abs(pos.x)) + this.player.position.y || !this.isReady) {
  561. this.ray.clear();
  562. this.topTween(1);
  563. for (let i = 0; i < this.ray.node.childrenCount; i++) {
  564. this.ray.node.children[i].getComponent(cc.Graphics).clear();
  565. }
  566. this.node.getChildByName('tipRay').getComponent(cc.Graphics).clear();
  567. this.isHide = true;
  568. return false;
  569. }
  570. this.isHide = false;
  571. return true;
  572. }
  573. /**
  574. * @description 计算射线
  575. * @param startLocation 起始位置 世界坐标系
  576. * @param vector_dir 单位方向向量
  577. */
  578. private drawRayCast(startLocation: cc.Vec2, vector_dir: cc.Vec2, graphic: cc.Graphics): void {
  579. if (this.specialBubbleType == 2) {
  580. this.specialBubbleIndex = [];
  581. const endLocation = startLocation.add(vector_dir.mul(1500));
  582. const results = cc.director.getPhysicsManager().rayCast(startLocation, endLocation, cc.RayCastType.AllClosest);
  583. this.drawAimLine(startLocation, results[results.length - 1].point, graphic);
  584. //计算激光经过的泡泡
  585. let result1 = cc.director.getPhysicsManager().rayCast(startLocation.sub(cc.v2(this.bubbleR - 1)), endLocation.sub(cc.v2(this.bubbleR - 1)), cc.RayCastType.AllClosest);
  586. for (let i in result1) {
  587. if (result1[i].collider.node.name == 'bubble') {
  588. let hitBubble = result1[i].collider.node.parent.getComponent('Bubble');
  589. this.specialBubbleIndex.push(cc.v2(hitBubble.i, hitBubble.j));
  590. }
  591. }
  592. let result2 = cc.director.getPhysicsManager().rayCast(startLocation.sub(cc.v2(-this.bubbleR + 1)), endLocation.sub(cc.v2(-this.bubbleR + 1)), cc.RayCastType.AllClosest);
  593. for (let i in result2) {
  594. if (result2[i].collider.node.name == 'bubble') {
  595. let hitBubble = result2[i].collider.node.parent.getComponent('Bubble');
  596. this.specialBubbleIndex.push(cc.v2(hitBubble.i, hitBubble.j));
  597. }
  598. }
  599. if (result1[result1.length - 1].collider.node.name != 'bubble' && result2[result2.length - 1].collider.node.name != 'bubble') {
  600. this.node.getChildByName('tipRay').getComponent(cc.Graphics).clear();
  601. }
  602. //加入点位
  603. if (this.specialBubbleIndex.length > 0) {
  604. let tipRay = this.node.getChildByName('tipRay').getComponent(cc.Graphics);
  605. tipRay.clear();
  606. this.unique();
  607. for (let i = 0; i < this.specialBubbleIndex.length; i++) {
  608. let pos = this.convertRowColToPos(this.specialBubbleIndex[i].x, this.specialBubbleIndex[i].y);
  609. pos = this.node.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(pos))
  610. tipRay.circle(pos.x, pos.y, this.bubbleR);
  611. }
  612. tipRay.stroke();
  613. }
  614. }
  615. else {
  616. const endLocation = startLocation.add(vector_dir.mul(10000));
  617. const results = cc.director.getPhysicsManager().rayCast(startLocation, endLocation, cc.RayCastType.Closest);
  618. const result = results[0];
  619. // 指定射线与穿过的碰撞体在哪一点相交。
  620. const point = result.point;
  621. this.drawAimLine(startLocation, point, graphic);
  622. //碰撞体
  623. const collider = result.collider.node.name;
  624. // 画入射线段
  625. if (collider == 'left' || collider == 'right') {
  626. // 指定碰撞体在相交点的表面的法线单位向量。
  627. const vector_n = result.normal;
  628. const vector_r = vector_dir.sub(vector_n.mul(2 * vector_dir.dot(vector_n)));
  629. this.drawRayCast(point, vector_r, graphic);
  630. }
  631. else {
  632. let hitBubble = result.collider.node.parent;
  633. if (collider == 'bubble') {
  634. this.bubbleIndex = this.setBubble(hitBubble.getComponent('Bubble').i, hitBubble.getComponent('Bubble').j, this.map.convertToNodeSpaceAR(point));
  635. }
  636. if (collider == 'top') {
  637. this.bubbleIndex = this.setBubble(-1, -1, this.map.convertToNodeSpaceAR(point));
  638. }
  639. this.specialBubbleIndex = [];
  640. switch (this.specialBubbleType) {
  641. case 1:
  642. this.bombBubble();
  643. break;
  644. case 3:
  645. this.omnipotentBubble();
  646. break;
  647. case 4:
  648. this.lightningBubble(hitBubble, collider == 'top' ? true : false);
  649. break;
  650. }
  651. let tipRay = this.node.getChildByName('tipRay').getComponent(cc.Graphics);
  652. tipRay.clear();
  653. // this.specialBubbleIndex.push(cc.v2(this.bubbleIndex.x, this.bubbleIndex.y));
  654. this.unique();
  655. for (let i = 0; i < this.specialBubbleIndex.length; i++) {
  656. let pos = this.convertRowColToPos(this.specialBubbleIndex[i].x, this.specialBubbleIndex[i].y);
  657. pos = this.node.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(pos))
  658. tipRay.circle(pos.x, pos.y, this.bubbleR);
  659. }
  660. tipRay.stroke();
  661. }
  662. }
  663. }
  664. /**
  665. * @description 画瞄准线
  666. * @param startLocation 起始位置 世界坐标系
  667. * @param endLocation 结束位置 世界坐标系
  668. */
  669. private drawAimLine(startLocation: cc.Vec2, endLocation: cc.Vec2, graphic: cc.Graphics): void {
  670. const graphic_startLocation = graphic.node.convertToNodeSpaceAR(startLocation);
  671. const graphic_endLocation = graphic.node.convertToNodeSpaceAR(endLocation);
  672. graphic.moveTo(graphic_startLocation.x, graphic_startLocation.y);
  673. /*画间隔圆线*/
  674. //圆与圆之间的间隔
  675. let delta = 60;
  676. //直线方向
  677. const vector_dir = endLocation.sub(startLocation);
  678. //圆的数量
  679. const total_count = Math.floor(vector_dir.mag() / delta);
  680. //每次间隔向量
  681. vector_dir.normalizeSelf().mulSelf(delta);
  682. for (let index = 0; index < total_count; index++) {
  683. graphic_startLocation.addSelf(vector_dir);
  684. this.rayPos.push(cc.v2(graphic_startLocation.x, graphic_startLocation.y));
  685. }
  686. this.rayPos.push(cc.v2(graphic_endLocation.x, graphic_endLocation.y));
  687. this.pathPos.push(cc.v2(graphic_endLocation.x, graphic_endLocation.y));
  688. }
  689. /**更新射线 */
  690. private updateRay(dt): void {
  691. this.ray.clear();
  692. for (let i = 0; i < this.ray.node.childrenCount; i++) {
  693. this.ray.node.children[i].getComponent(cc.Graphics).clear();
  694. }
  695. // (0.4:min+5:max)/2
  696. let offset: number = 10;
  697. for (let i = 0; i < this.rayPos.length; i++) {
  698. if (i % 2 == 0) {
  699. this.ray.circle(this.rayPos[i].x, this.rayPos[i].y, offset + this.r);
  700. for (let j = 0; j < this.ray.node.childrenCount; j++) {
  701. this.ray.node.children[j].getComponent(cc.Graphics).circle(this.rayPos[i].x, this.rayPos[i].y, offset + this.r - (j + 1) * 3);
  702. }
  703. }
  704. else {
  705. this.ray.circle(this.rayPos[i].x, this.rayPos[i].y, offset - this.r);
  706. for (let j = 0; j < this.ray.node.childrenCount; j++) {
  707. this.ray.node.children[j].getComponent(cc.Graphics).circle(this.rayPos[i].x, this.rayPos[i].y, offset - this.r - (j + 1) * 3);
  708. }
  709. }
  710. }
  711. this.r += this.op * 10 * dt;
  712. if (Math.abs(this.r) > 3) {
  713. this.op = -this.op;
  714. }
  715. this.ray.fill();
  716. for (let i = 0; i < this.ray.node.childrenCount; i++) {
  717. this.ray.node.children[i].getComponent(cc.Graphics).fill();
  718. }
  719. }
  720. /**创建小球 */
  721. private creatBubble(i: number, j: number, color: number): void {
  722. let node = cc.instantiate(this.bubble);
  723. node.position = this.convertRowColToPos(i, j);
  724. if (this.specialBubbleType == 0) {
  725. node.getComponent(cc.Sprite).spriteFrame = this.bubbleSpriteFrame[color - 1];
  726. }
  727. else {
  728. node.getComponent(cc.Sprite).spriteFrame = this.specialBubbleSpriteFrame[color - 1];
  729. }
  730. node.parent = this.map;
  731. node.getComponent('Bubble').init(i, j, color);
  732. node.setContentSize(this.bubbleR * 2, this.bubbleR * 2);
  733. node.children[0].getComponent(cc.PhysicsCircleCollider).radius = this.bubbleR;
  734. node.children[0].getComponent(cc.PhysicsCircleCollider).apply();
  735. GameDataCenter.bubbles[i][j] = node;
  736. if (color >= 1 && color <= 6) { this.colorCount[color - 1]++; }
  737. }
  738. /**创建预发射小球 */
  739. private createShootBubble(isInit: boolean = false): void {
  740. if (!isInit) {
  741. this.shootBubble = this.preBubble;
  742. this.ray.fillColor = this.rayColor[this.shootBubble.getComponent('Bubble').color - 1];
  743. this.bubbleCount--;
  744. if (this.bubbleCount == 0) {
  745. GameDataCenter.tipType = 0;
  746. UIManager.open('tip:TipPanel');
  747. }
  748. if (this.bubbleCount == 3) {
  749. GameDataCenter.tipType = 3;
  750. UIManager.open('tip:TipPanel');
  751. }
  752. if (this.bubbleCount == 10) {
  753. GameDataCenter.tipType = 1;
  754. UIManager.open('tip:TipPanel');
  755. }
  756. }
  757. let node = cc.instantiate(this.shootBubblePre);
  758. let pos = this.player.convertToNodeSpaceAR(this.startPos);
  759. let color = this.randNum();
  760. node.position = cc.v3(pos.x + 60, pos.y - 60);
  761. node.parent = this.player;
  762. node.getChildByName('sprite').getComponent(cc.Sprite).spriteFrame = this.bubbleSpriteFrame[color - 1];
  763. node.setContentSize(this.bubbleR * 2, this.bubbleR * 2);
  764. node.getComponent('Bubble').color = color;
  765. node.scale = 0;
  766. this.preBubble = node;
  767. }
  768. /**发射小球切换动画 */
  769. private switchShootBubble(): void {
  770. this.scheduleOnce(() => {
  771. this.specialBubbleType = 0;
  772. let pos = this.player.convertToNodeSpaceAR(this.startPos);
  773. if (this.colorCount[this.shootBubble.getComponent('Bubble').color - 1] == 0) {
  774. let color = this.randNum();
  775. this.shootBubble.getComponent('Bubble').color = color;
  776. this.shootBubble.getChildByName('sprite').getComponent(cc.Sprite).spriteFrame = this.bubbleSpriteFrame[color - 1];
  777. }
  778. cc.tween(this.shootBubble).to(0.5, { position: cc.v3(pos.x, pos.y), scale: 1 }).start();
  779. cc.tween(this.preBubble).to(0.5, { scale: 0.75 }).start();
  780. this.ray.fillColor = this.rayColor[this.shootBubble.getComponent('Bubble').color - 1];
  781. this.player.getChildByName('bubbleCount').getComponent(cc.Label).string = `${this.bubbleCount}`
  782. this.scheduleOnce(() => {
  783. this.isReady = true;
  784. }, 0.5);
  785. this.player.getChildByName('icon').active = true;
  786. }, 0.1);
  787. }
  788. /**特殊球切换 */
  789. private switchSpecialBubble(op: number): void {
  790. let specialBubble = this.ui.getChildByName('specialBubble');
  791. for (let i = 0; i < specialBubble.childrenCount; i++) {
  792. cc.tween(specialBubble.children[i])
  793. .by(0.5, { y: op * -200, opacity: op * -255 })
  794. .call(() => {
  795. if (op == 1) {
  796. this.ui.getChildByName('cancel').active = true;
  797. specialBubble.children[i].getComponent(cc.Button).interactable = true;
  798. }
  799. })
  800. .start();
  801. }
  802. if (op == 1) {
  803. this.setspecialColor();
  804. let node = cc.instantiate(this.shootBubblePre);
  805. let pos = this.player.convertToNodeSpaceAR(this.startPos);
  806. node.position = cc.v3(pos.x, pos.y);
  807. node.parent = this.player;
  808. node.getChildByName('sprite').getComponent(cc.Sprite).spriteFrame = this.specialBubbleSpriteFrame[this.specialBubbleType - 1];
  809. node.setContentSize(this.bubbleR * 2, this.bubbleR * 2);
  810. node.scale = 0;
  811. let effect = cc.instantiate(this.specialBubbleEffect[this.specialBubbleType - 1]);
  812. effect.parent = node;
  813. this.specialBubble = node;
  814. cc.tween(this.specialBubble)
  815. .to(0.3, { scale: 1 })
  816. .start();
  817. cc.tween(this.shootBubble)
  818. .to(0.3, { scale: 0, opacity: 0 })
  819. .call(() => {
  820. this.shootBubble.active = false;
  821. this.shootBubble.opacity = 255;
  822. this.shootBubble.scale = 0;
  823. this.shootBubble.position = cc.v3(pos.x + 60, pos.y - 60);
  824. })
  825. .start();
  826. cc.tween(this.preBubble)
  827. .to(0.3, { scale: 0 })
  828. .start();
  829. }
  830. else {
  831. this.ray.node.removeAllChildren();
  832. this.specialBubble.destroy();
  833. this.shootBubble.active = true;
  834. cc.tween(this.shootBubble).to(0.3, { scale: 0.75 }).start();
  835. if (!this.isWin) { this.switchShootBubble(); }
  836. this.ui.getChildByName('cancel').active = false;
  837. }
  838. }
  839. /**小球运动 */
  840. private bubbleMove(i): void {
  841. // let pos: cc.Vec2 = this.player.convertToNodeSpaceAR(this.ray.node.convertToWorldSpaceAR(this.rayPos[i]));
  842. // let end: cc.Vec2 = this.player.convertToNodeSpaceAR(this.ray.node.convertToWorldSpaceAR(this.rayPos[i - 1]));
  843. let pos: cc.Vec2 = this.player.convertToNodeSpaceAR(this.ray.node.convertToWorldSpaceAR(this.pathPos[i]));
  844. let end: cc.Vec2 = this.player.convertToNodeSpaceAR(this.ray.node.convertToWorldSpaceAR(this.pathPos[i - 1]));
  845. if (this.specialBubbleType == 2) {
  846. this.combo++;
  847. this.node.getChildByName('tipRay').getComponent(cc.Graphics).clear();
  848. let node = cc.instantiate(this.laser_gj);
  849. node.parent = this.specialBubble;
  850. node.angle = this.vectorsToDegree(this.startPos, this.laserVec);
  851. for (let i in this.specialBubbleIndex) {
  852. let color = GameDataCenter.bubbles[this.specialBubbleIndex[i].x][this.specialBubbleIndex[i].y].getComponent('Bubble').color;
  853. if (color >= 1 && color <= 6) { this.colorCount[color - 1]--; }
  854. GameDataCenter.bubbles[this.specialBubbleIndex[i].x][this.specialBubbleIndex[i].y].getComponent('Bubble').playDeathAnimation(this.combo, this.specialBubbleType);
  855. this.changeUi('score', this.combo * 10);
  856. }
  857. this.isSuspension();
  858. return;
  859. }
  860. cc.tween(this.specialBubbleType == 0 ? this.shootBubble : this.specialBubble)
  861. .to(Math.floor(pos.sub(end).mag()) / (1000 * 2), { position: cc.v3(pos.x, pos.y, 0) })
  862. .call(() => {
  863. if (i < this.pathPos.length - 1) {
  864. this.bubbleMove(i + 1);
  865. }
  866. else {
  867. if (this.specialBubbleType == 0) {
  868. this.creatBubble(this.bubbleIndex.x, this.bubbleIndex.y, this.shootBubble.getComponent('Bubble').color);
  869. this.crashTween(this.bubbleIndex.x, this.bubbleIndex.y);
  870. this.shootBubble.destroy();
  871. this.isElimination();
  872. }
  873. else {
  874. this.combo++;
  875. this.node.getChildByName('tipRay').getComponent(cc.Graphics).clear();
  876. if (this.specialBubbleType == 4) {
  877. if (!GameDataCenter.bubbles[this.thunderIndex.x][this.thunderIndex.y]) {
  878. this.creatBubble(this.thunderIndex.x, this.thunderIndex.y, this.specialBubbleType);
  879. this.specialBubbleIndex.push(cc.v2(this.thunderIndex.x, this.thunderIndex.y));
  880. }
  881. let node = cc.instantiate(this.thunder_gj);
  882. node.parent = GameDataCenter.bubbles[this.thunderIndex.x][this.thunderIndex.y];
  883. node.position = node.parent.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(cc.v3(0, this.convertRowColToPos(this.thunderIndex.x, this.thunderIndex.y).y)));
  884. let children = node.getChildByName('qiu')
  885. children.position = node.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(this.convertRowColToPos(this.thunderIndex.x, this.thunderIndex.y)));
  886. }
  887. else {
  888. this.creatBubble(this.bubbleIndex.x, this.bubbleIndex.y, this.specialBubbleType);
  889. this.specialBubbleIndex.push(cc.v2(this.bubbleIndex.x, this.bubbleIndex.y));
  890. }
  891. for (let i in this.specialBubbleIndex) {
  892. let color = GameDataCenter.bubbles[this.specialBubbleIndex[i].x][this.specialBubbleIndex[i].y].getComponent('Bubble').color;
  893. if (color >= 1 && color <= 6) { this.colorCount[color - 1]--; }
  894. GameDataCenter.bubbles[this.specialBubbleIndex[i].x][this.specialBubbleIndex[i].y].getComponent('Bubble').playDeathAnimation(this.combo, this.specialBubbleType);
  895. this.changeUi('score', this.combo * 10);
  896. }
  897. this.isSuspension();
  898. this.specialBubble.destroy();
  899. }
  900. }
  901. })
  902. .start();
  903. }
  904. /**更新地图大小及位置 */
  905. private setMapPosition(op: number = 1): void {
  906. let offset: number = this.bubbleR * Math.sqrt(3);
  907. cc.tween(this.map)
  908. .by(Math.max(0.03 * op, 0.3), { y: op * offset })
  909. .call(() => {
  910. for (let i = 0; i < this.map.childrenCount; i++) {
  911. this.map.children[i].children[0].position = cc.v3(0, 0, 0);
  912. this.map.children[i].children[0].getComponent(cc.RigidBody).syncPosition(false);
  913. }
  914. })
  915. .start();
  916. cc.tween(this.walls.getChildByName('top'))
  917. .by(Math.max(0.03 * op, 0.3), { y: op * offset })
  918. .start();
  919. // this.schedule(() => {
  920. // this.showBubble();
  921. // }, 0.1, Math.ceil(Math.max(0.02 * op, 0.3) / 0.1) + 1);
  922. }
  923. /**泡泡位置校正 */
  924. private setBubble(i: number, j: number, position: cc.Vec2): cc.Vec2 {
  925. let mag: number = 99999;
  926. let index: cc.Vec2 = cc.v2();
  927. if (i == -1 && j == -1) {
  928. index.x = 0;
  929. for (let k = 0; k < 11; k++) {
  930. if (GameDataCenter.bubbles[0][k]) { continue; }
  931. let t: cc.Vec3 = this.convertRowColToPos(0, k);
  932. let p: cc.Vec2 = cc.v2(t.x, t.y);
  933. if (p.sub(position).mag() < mag) {
  934. mag = p.sub(position).mag();
  935. index.y = k;
  936. }
  937. }
  938. }
  939. else {
  940. this.traversal(i, j, (row: number, col: number) => {
  941. if (GameDataCenter.bubbles[row][col]) return true;
  942. let t: cc.Vec3 = this.convertRowColToPos(row, col);
  943. let p: cc.Vec2 = cc.v2(t.x, t.y);
  944. if (p.sub(position).mag() < mag) {
  945. mag = p.sub(position).mag();
  946. index.x = row;
  947. index.y = col;
  948. }
  949. })
  950. }
  951. return index;
  952. }
  953. /**检测泡泡是否消除 */
  954. private isElimination(): void {
  955. // 记录消除行列值
  956. let record: cc.Vec2[] = [];
  957. let color = this.shootBubble.getComponent('Bubble').color;
  958. GameDataCenter.bubbles[this.bubbleIndex.x][this.bubbleIndex.y].getComponent('Bubble').isVisited = true;
  959. record.push(cc.v2(this.bubbleIndex.x, this.bubbleIndex.y));
  960. this.traversalAll(this.bubbleIndex.x, this.bubbleIndex.y, (row: number, col: number) => {
  961. // if (row < GameDataCenter.bubbles.length - this.showCount - 1) return true;
  962. let nodeData = GameDataCenter.bubbles[row][col].getComponent('Bubble');
  963. // 如果被访问过
  964. if (nodeData.isVisited) return true;
  965. // 如果颜色不同
  966. if (nodeData.color !== color) return true;
  967. // 符合条件
  968. nodeData.isVisited = true;
  969. record.push(cc.v2(row, col));
  970. })
  971. let count: number = 0;
  972. for (let row = 0; row < GameDataCenter.bubbles.length; row++) {
  973. for (let col = 0; col < GameDataCenter.bubbles[row].length; col++) {
  974. if (!GameDataCenter.bubbles[row][col]) continue;
  975. if (GameDataCenter.bubbles[row][col].getComponent('Bubble').isVisited) {
  976. GameDataCenter.bubbles[row][col].getComponent('Bubble').isVisited = false;
  977. count++;
  978. }
  979. }
  980. }
  981. if (count >= 3) {
  982. this.combo++;
  983. // 执行消除
  984. for (let i in record) {
  985. this.scheduleOnce(() => {
  986. this.isIceBubble(record[i].x, record[i].y, GameDataCenter.bubbles[record[i].x][record[i].y].getComponent('Bubble').color);
  987. this.colorCount[GameDataCenter.bubbles[record[i].x][record[i].y].getComponent('Bubble').color - 1]--;
  988. GameDataCenter.bubbles[record[i].x][record[i].y].getComponent('Bubble').playDeathAnimation(this.combo);
  989. }, +i * (0.04 - record.length * 0.001));
  990. }
  991. this.scheduleOnce(() => {
  992. this.changeUi('score', 10 * this.combo * count);
  993. // this.scheduleOnce(() => {
  994. // Audio.playSoundByPath('game:res/snd/score');
  995. // }, 0.5);
  996. //分数激励
  997. let node = cc.instantiate(this.scorePrefab);
  998. node.parent = this.node;
  999. let pos = this.convertRowColToPos(this.bubbleIndex.x, this.bubbleIndex.y);
  1000. pos = this.node.convertToNodeSpaceAR(this.map.convertToWorldSpaceAR(pos));
  1001. node.position = cc.v3(pos.x, pos.y - 100);
  1002. node.children[0].getComponent(cc.Label).string = `${count * this.combo * 10}`;
  1003. node.getChildByName(this.appraise[Math.floor(Math.random() * 3)]).active = true;
  1004. cc.tween(node)
  1005. .by(0.5, { y: 100 })
  1006. .removeSelf()
  1007. .start();
  1008. if (count > 10) {
  1009. node = cc.instantiate(this.appraisePrefab);
  1010. node.parent = this.node;
  1011. node.scale = 0;
  1012. node.children[Math.floor(Math.random() * 3)].active = true;
  1013. }
  1014. cc.tween(node)
  1015. .to(0.2, { scale: 1 })
  1016. .delay(1)
  1017. .to(0.2, { scale: 0 })
  1018. .removeSelf()
  1019. .start();
  1020. this.isSuspension();
  1021. }, record.length * (0.04 - record.length * 0.001));
  1022. } else {
  1023. this.combo = 0;
  1024. //数组变化及地图移动
  1025. if (this.bubbleIndex.x >= GameDataCenter.bubbles.length - 1) {
  1026. GameDataCenter.bubbles[GameDataCenter.bubbles.length] = []
  1027. if (GameDataCenter.bubbles.length > 10) {
  1028. this.setMapPosition();
  1029. }
  1030. }
  1031. //创建下一个小球
  1032. this.scheduleOnce(() => {
  1033. this.createShootBubble();
  1034. this.switchShootBubble();
  1035. }, 0);
  1036. }
  1037. }
  1038. /**悬空检测 */
  1039. private isSuspension(): void {
  1040. this.scheduleOnce(() => {
  1041. for (let i = 0; i < GameDataCenter.bubbles[0].length; i++) {
  1042. // 执行最上的一排泡泡
  1043. if (!GameDataCenter.bubbles[0][i]) continue;
  1044. this.traversalAll(0, i, (row: number, col: number) => {
  1045. let nodeData = GameDataCenter.bubbles[row][col].getComponent('Bubble');
  1046. if (nodeData.isVisited) return true;
  1047. // 符合条件
  1048. nodeData.isVisited = true;
  1049. nodeData.isLinked = true;
  1050. }, true);
  1051. }
  1052. let count: number = 0;
  1053. for (let row = 0; row < GameDataCenter.bubbles.length; row++) {
  1054. for (let col = 0; col < GameDataCenter.bubbles[row].length; col++) {
  1055. if (!GameDataCenter.bubbles[row][col]) continue;
  1056. if (!GameDataCenter.bubbles[row][col].getComponent('Bubble').isLinked) {
  1057. this.scheduleOnce(() => {
  1058. let color = GameDataCenter.bubbles[row][col].getComponent('Bubble').color;
  1059. if (color >= 1 && color <= 6) { this.colorCount[color - 1]--; }
  1060. GameDataCenter.bubbles[row][col].getComponent('Bubble').playDownAnimation(this.combo * 2, this.map.convertToNodeSpaceAR(this.startPos));
  1061. }, count * 0.02);
  1062. count++;
  1063. } else {
  1064. GameDataCenter.bubbles[row][col].getComponent('Bubble').isVisited = false;
  1065. GameDataCenter.bubbles[row][col].getComponent('Bubble').isLinked = false;
  1066. }
  1067. }
  1068. }
  1069. this.scheduleOnce(() => {
  1070. if (count > 0) { this.changeUi('score', 10 * this.combo * count * 2); }
  1071. this.removeEmpty();
  1072. }, count * 0.02 + count > 0 ? 1.5 : 0);
  1073. }, 0);
  1074. }
  1075. /**冰球检测*/
  1076. private isIceBubble(i: number, j: number, color: number): void {
  1077. this.traversal(i, j, (row: number, col: number) => {
  1078. if (!GameDataCenter.bubbles[row] || !GameDataCenter.bubbles[row][col]) return true;
  1079. if (GameDataCenter.bubbles[row][col].getComponent('Bubble').color == 6) {
  1080. GameDataCenter.bubbles[row][col].destroy();
  1081. Audio.playSoundByPath('game:res/snd/ice');
  1082. this.colorCount[5]--;
  1083. this.creatBubble(row, col, color);
  1084. }
  1085. })
  1086. }
  1087. /**碰撞动画 */
  1088. private crashTween(i: number, j: number): void {
  1089. this.traversal(i, j, (row: number, col: number) => {
  1090. if (!GameDataCenter.bubbles[row] || !GameDataCenter.bubbles[row][col]) return true;
  1091. let start = this.convertRowColToPos(i, j);
  1092. let end = this.convertRowColToPos(row, col);
  1093. let dir = end.sub(start);
  1094. cc.tween(GameDataCenter.bubbles[row][col])
  1095. .by(0.1, { position: dir.normalize().mul(10) })
  1096. .by(0.1, { position: dir.normalize().mul(-10) })
  1097. .start();
  1098. })
  1099. }
  1100. /**炸弹 */
  1101. private bombBubble(): void {
  1102. this.traversal(this.bubbleIndex.x, this.bubbleIndex.y, (row: number, col: number) => {
  1103. this.traversal(row, col, (i, j) => {
  1104. if (!GameDataCenter.bubbles[i] || !GameDataCenter.bubbles[i][j]) return true;
  1105. this.specialBubbleIndex.push(cc.v2(i, j));
  1106. })
  1107. })
  1108. }
  1109. /**七色 */
  1110. private omnipotentBubble(): void {
  1111. this.traversal(this.bubbleIndex.x, this.bubbleIndex.y, (row: number, col: number) => {
  1112. if (!GameDataCenter.bubbles[row] || !GameDataCenter.bubbles[row][col]) return true;
  1113. let color = GameDataCenter.bubbles[row][col].getComponent('Bubble').color;
  1114. this.traversalAll(row, col, (i: number, j: number) => {
  1115. let nodeData = GameDataCenter.bubbles[i][j].getComponent('Bubble');
  1116. // 如果被访问过
  1117. if (nodeData.isVisited) return true;
  1118. // 如果颜色不同
  1119. if (nodeData.color !== color) return true;
  1120. // 符合条件
  1121. nodeData.isVisited = true;
  1122. })
  1123. });
  1124. for (let row = 0; row < GameDataCenter.bubbles.length; row++) {
  1125. for (let col = 0; col < GameDataCenter.bubbles[row].length; col++) {
  1126. if (!GameDataCenter.bubbles[row][col]) continue;
  1127. if (GameDataCenter.bubbles[row][col].getComponent('Bubble').isVisited) {
  1128. GameDataCenter.bubbles[row][col].getComponent('Bubble').isVisited = false;
  1129. this.specialBubbleIndex.push(cc.v2(row, col));
  1130. }
  1131. }
  1132. }
  1133. }
  1134. /**闪电 */
  1135. private lightningBubble(hitBubble: cc.Node, isTop: boolean): void {
  1136. if (isTop) {
  1137. this.thunderIndex = cc.v2(this.bubbleIndex.x, this.bubbleIndex.y);
  1138. }
  1139. else {
  1140. this.thunderIndex = cc.v2(hitBubble.getComponent('Bubble').i, hitBubble.getComponent('Bubble').j);
  1141. }
  1142. for (let i = 0; i < GameDataCenter.bubbles[this.thunderIndex.x].length; i++) {
  1143. let node = GameDataCenter.bubbles[this.thunderIndex.x][i]
  1144. if (!node) { continue; }
  1145. this.specialBubbleIndex.push(cc.v2(node.getComponent('Bubble').i, node.getComponent('Bubble').j));
  1146. }
  1147. }
  1148. /**清空空数组 */
  1149. private removeEmpty(): void {
  1150. let removeCount: number = 0;
  1151. for (let i = GameDataCenter.bubbles.length - 2; i >= 0; i--) {
  1152. let count = 0;
  1153. for (let j = 0; j < GameDataCenter.bubbles[i].length; j++) {
  1154. if (GameDataCenter.bubbles[i][j]) {
  1155. count++;
  1156. }
  1157. }
  1158. if (count == 0) {
  1159. GameDataCenter.bubbles.length--;
  1160. if (GameDataCenter.bubbles.length >= 10) { removeCount++; }
  1161. }
  1162. }
  1163. this.setMapPosition(-removeCount);
  1164. let sum: number = 0;
  1165. for (let i = 0; i < this.colorCount.length; i++) {
  1166. sum += this.colorCount[i];
  1167. }
  1168. let count = 0;
  1169. if (sum == 0) {
  1170. this.isWin = true;
  1171. Audio.playSoundByPath('game:res/snd/victory');
  1172. GameDataCenter.gameLevel++;
  1173. for (let i = 0; i < GameDataCenter.bubbles.length; i++) {
  1174. for (let j = 0; j < GameDataCenter.bubbles[i].length; j++) {
  1175. if (!GameDataCenter.bubbles[i][j]) { continue; }
  1176. this.scheduleOnce(() => {
  1177. GameDataCenter.bubbles[i][j].getComponent('Bubble').playDownAnimation(this.combo * 2, this.map.convertToNodeSpaceAR(this.startPos));
  1178. }, count * 0.01);
  1179. count++;
  1180. }
  1181. }
  1182. if (count > 0) {
  1183. this.scheduleOnce(() => {
  1184. this.changeUi('score', this.combo * 2 * count * 10);
  1185. }, count * 0.01);
  1186. }
  1187. this.scheduleOnce(() => {
  1188. this.initMap();
  1189. }, 2 + count * 0.01);
  1190. }
  1191. this.scheduleOnce(() => {
  1192. if (this.specialBubbleType == 0) {
  1193. this.scheduleOnce(() => {
  1194. this.createShootBubble();
  1195. this.switchShootBubble();
  1196. }, this.isWin ? 3 : 0);
  1197. }
  1198. else {
  1199. if (GameDataCenter.specialBubbles[this.specialBubbleType - 1] > 0) {
  1200. this.changeUi(`special${this.specialBubbleType}`, -1);
  1201. }
  1202. else if (GameDataCenter.coin >= 100) {
  1203. this.changeUi('coin', -100);
  1204. }
  1205. this.scheduleOnce(() => {
  1206. this.switchSpecialBubble(-1);
  1207. }, this.specialBubbleType == 2 ? 1 : 0);
  1208. }
  1209. }, count * 0.01);
  1210. }
  1211. /**传入二维数组行列, 返回对应位置坐标 */
  1212. private convertRowColToPos(row: number, col: number): cc.Vec3 {
  1213. let posX: number = this.bubbleR * ((row % 2) + 1) + col * this.bubbleR * 2 - this.screenW / 2;
  1214. let posY: number = this.screenH - (this.bubbleR + this.bubbleR * row * Math.sqrt(3));
  1215. return cc.v3(posX, posY);
  1216. }
  1217. /**计算向量与y轴之间的夹角 */
  1218. private vectorsToDegree(comVec, dirVec) {
  1219. // 求方向向量与对比向量间的弧度
  1220. let dir = comVec.sub(dirVec);
  1221. let radian = dir.signAngle(cc.v2(1, 0));
  1222. // 将弧度转换为角度
  1223. let degree = cc.misc.radiansToDegrees(radian);
  1224. return Math.round(-(degree - 90));
  1225. }
  1226. /**随机颜色函数 */
  1227. private randNum(): number {
  1228. if (GameDataCenter.gameLevel == 1) {
  1229. if (LevelConfig.level[1].index < 4) { return LevelConfig.level[1].bubble[LevelConfig.level[1].index++]; }
  1230. }
  1231. let color: number[] = [];
  1232. for (let i = 0; i < this.colorCount.length - 1; i++) {
  1233. if (this.colorCount[i] != 0) {
  1234. color.push(i + 1);
  1235. }
  1236. }
  1237. let min: number = 0;
  1238. let max: number = color.length - 1;
  1239. // random 0 - 1 不包括 1
  1240. let random = min + Math.floor((max - min + 1) * Math.random())
  1241. if (color.length == 0) {
  1242. min = 1;
  1243. max = this.colorCount.length - 1
  1244. random = min + Math.floor((max - min + 1) * Math.random())
  1245. return random;
  1246. }
  1247. return color[random];
  1248. }
  1249. /**特殊消除球向量数组去重 */
  1250. private unique(): void {
  1251. let array: cc.Vec2[] = []
  1252. for (let i in this.specialBubbleIndex) {
  1253. let isExit = false;
  1254. for (let j in array) {
  1255. if (this.specialBubbleIndex[i].x == array[j].x && this.specialBubbleIndex[i].y == array[j].y) {
  1256. isExit = true;
  1257. break;
  1258. }
  1259. }
  1260. if (!isExit) {
  1261. array.push(cc.v2(this.specialBubbleIndex[i].x, this.specialBubbleIndex[i].y))
  1262. }
  1263. }
  1264. this.specialBubbleIndex = array;
  1265. }
  1266. /**设置特殊球瞄准线线段颜色 */
  1267. private setspecialColor(): void {
  1268. let specialColor = this.specialColor[this.specialBubbleType - 1];
  1269. this.ray.fillColor = specialColor[0];
  1270. for (let i = 1; i < specialColor.length; i++) {
  1271. let node = cc.instantiate(this.rayPrefab);
  1272. node.parent = this.ray.node;
  1273. let graphic = node.getComponent(cc.Graphics);
  1274. graphic.fillColor = specialColor[i];
  1275. }
  1276. }
  1277. /**ui变化 */
  1278. private changeUi(type: string, num: number = 0): void {
  1279. if (type == 'coin') {
  1280. this.ui.getChildByName('topPanel').getChildByName('coin').getChildByName('num').children[0].getComponent(cc.Label).string = `${GameDataCenter.coin}`;
  1281. if (num == 0) { return; }
  1282. let t: number = GameDataCenter.coin;
  1283. GameDataCenter.coin += num;
  1284. for (let i = 0; i < Math.abs(GameDataCenter.coin - t); i++) {
  1285. this.scheduleOnce(() => {
  1286. num > 0 ? t++ : t--;
  1287. this.ui.getChildByName('topPanel').getChildByName('coin').getChildByName('num').children[0].getComponent(cc.Label).string = `${t}`;
  1288. }, 0.002 * i);
  1289. }
  1290. let specialBubble = this.ui.getChildByName('specialBubble');
  1291. for (let i = 0; i < specialBubble.childrenCount; i++) {
  1292. specialBubble.children[i].getChildByName('null').getChildByName('icon').getComponent(cc.Sprite).spriteFrame = GameDataCenter.coin >= 100 ? this.iconSpriteFrame[2] : this.iconSpriteFrame[0];
  1293. specialBubble.children[i].getChildByName('null').getChildByName('label').getComponent(cc.Label).string = GameDataCenter.coin >= 100 ? '100' : ':1';
  1294. }
  1295. }
  1296. else if (type == 'score') {
  1297. if (num == 0) {
  1298. this.score = 0;
  1299. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('scoreLabel').getComponent(cc.Label).string = `得分:${this.score}`;
  1300. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('progressBar').getComponent(cc.ProgressBar).progress = 0;
  1301. for (let i = 1; i <= 3; i++) {
  1302. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName(`star${i}`).getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[3];
  1303. }
  1304. return;
  1305. }
  1306. let t = this.score;
  1307. this.score += num;
  1308. for (let i = 0; i < Math.abs(this.score - t); i++) {
  1309. this.scheduleOnce(() => {
  1310. num > 0 ? t++ : t--;
  1311. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('scoreLabel').getComponent(cc.Label).string = `得分:${t}`;
  1312. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('progressBar').getComponent(cc.ProgressBar).progress = t / this.perfectScore;
  1313. }, 0.5 * i / num);
  1314. }
  1315. this.scheduleOnce(() => {
  1316. if (this.score >= this.perfectScore && this.star == 2) {
  1317. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('star3').getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[4];
  1318. this.star++;
  1319. }
  1320. if (this.score >= this.perfectScore * 0.7 && this.star == 1) {
  1321. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('star2').getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[4];
  1322. this.star++;
  1323. }
  1324. if (this.score >= this.perfectScore * 0.2 && this.star == 0) {
  1325. this.ui.getChildByName('topPanel').getChildByName('score').getChildByName('star1').getComponent(cc.Sprite).spriteFrame = this.iconSpriteFrame[4];
  1326. this.star++;
  1327. }
  1328. }, 0.5);
  1329. }
  1330. else if (type.substring(0, type.length - 1) == 'special') {
  1331. let specialBubble = this.ui.getChildByName('specialBubble');
  1332. let enableSwitch: Function = (i) => {
  1333. specialBubble.children[i].getChildByName('num').active = GameDataCenter.specialBubbles[i] <= 0 ? false : true;
  1334. specialBubble.children[i].getChildByName('null').active = GameDataCenter.specialBubbles[i] <= 0 ? true : false;
  1335. specialBubble.children[i].getChildByName('null').getChildByName('icon').getComponent(cc.Sprite).spriteFrame = GameDataCenter.coin >= 100 ? this.iconSpriteFrame[2] : this.iconSpriteFrame[0];
  1336. specialBubble.children[i].getChildByName('null').getChildByName('label').getComponent(cc.Label).string = GameDataCenter.coin >= 100 ? '100' : ':1';
  1337. specialBubble.children[i].getChildByName('null').getChildByName('icon').setContentSize(GameDataCenter.coin >= 100 ? cc.size(40, 40) : cc.size(40, 30));
  1338. }
  1339. for (let i = 0; i < specialBubble.childrenCount; i++) {
  1340. specialBubble.children[i].getChildByName('num').getChildByName('label').getComponent(cc.Label).string = `${GameDataCenter.specialBubbles[i]}`;
  1341. enableSwitch(i);
  1342. }
  1343. let specialBubbleType = (+type[type.length - 1]) - 1;
  1344. if (specialBubbleType < 0 || num == 0) { return; }
  1345. let t: number = GameDataCenter.specialBubbles[specialBubbleType];
  1346. let array = GameDataCenter.specialBubbles;
  1347. array[specialBubbleType] += num;
  1348. GameDataCenter.specialBubbles = array;
  1349. for (let i = 0; i < Math.abs(GameDataCenter.specialBubbles[specialBubbleType] - t); i++) {
  1350. this.scheduleOnce(() => {
  1351. num > 0 ? t++ : t--;
  1352. specialBubble.children[specialBubbleType].getChildByName('num').getChildByName('label').getComponent(cc.Label).string = `${t}`;
  1353. }, 0.1 * i);
  1354. }
  1355. enableSwitch(specialBubbleType);
  1356. }
  1357. else if (type == 'ingot') {
  1358. }
  1359. }
  1360. /**遍历小球一周 */
  1361. private traversal(i: number, j: number, callback: Function): void {
  1362. let judge: Function = (row: number, col: number) => {
  1363. let leftTop = col;
  1364. // 根据不同的行做偏移
  1365. if (row % 2 === 0) {
  1366. leftTop = col - 1;
  1367. }
  1368. // 每个泡泡周围有6个,依次检测
  1369. // 左上
  1370. test(row - 1, leftTop);
  1371. //右上
  1372. test(row - 1, leftTop + 1);
  1373. //左
  1374. test(row, col - 1);
  1375. //右
  1376. test(row, col + 1);
  1377. //左下
  1378. test(row + 1, leftTop);
  1379. //右下
  1380. test(row + 1, leftTop + 1);
  1381. }
  1382. let test: Function = (row: number, col: number) => {
  1383. if (row < 0) return;
  1384. if (col < 0 || col >= 11) return;
  1385. if (row % 2 == 1 && (col < 0 || col >= 10)) { return; }
  1386. if (callback(row, col)) return;
  1387. }
  1388. judge(i, j);
  1389. }
  1390. /**遍历所有小球 */
  1391. private traversalAll(i: number, j: number, callback: Function, isDFS: boolean = false): void {
  1392. if (isDFS) {
  1393. //深搜
  1394. let test: Function = (row: number, col: number) => {
  1395. if (!GameDataCenter.bubbles[row] || !GameDataCenter.bubbles[row][col]) return;
  1396. if (row < 0) return;
  1397. if (col < 0 || col >= 11) return;
  1398. if (row % 2 == 1 && (col < 0 || col >= 10)) { return; }
  1399. if (callback(row, col)) return;
  1400. let leftTop = col;
  1401. if (row % 2 === 0) {
  1402. leftTop = col - 1;
  1403. }
  1404. // 每个泡泡周围有6个,依次检测
  1405. // 左上
  1406. test(row - 1, leftTop);
  1407. //右上
  1408. test(row - 1, leftTop + 1);
  1409. //左
  1410. test(row, col - 1);
  1411. //右
  1412. test(row, col + 1);
  1413. //左下
  1414. test(row + 1, leftTop);
  1415. //右下
  1416. test(row + 1, leftTop + 1);
  1417. }
  1418. test(i, j);
  1419. }
  1420. else {
  1421. //广搜
  1422. let indexs: cc.Vec2[] = [];
  1423. indexs.push(cc.v2(i, j));
  1424. while (indexs.length != 0) {
  1425. let index = indexs[0];
  1426. indexs.shift();
  1427. this.traversal(index.x, index.y, (row: number, col: number) => {
  1428. if (!GameDataCenter.bubbles[row] || !GameDataCenter.bubbles[row][col]) return;
  1429. if (row < 0) return;
  1430. if (col < 0 || col >= 11) return;
  1431. if (row % 2 == 1 && (col < 0 || col >= 10)) { return; }
  1432. if (callback(row, col)) return;
  1433. indexs.push(cc.v2(row, col));
  1434. })
  1435. }
  1436. }
  1437. }
  1438. /**倒计时回调 */
  1439. private online(): void {
  1440. this.onlineTime--;
  1441. let mm = Math.floor(this.onlineTime / 60);
  1442. let ss = this.onlineTime % 60;
  1443. this.ui.getChildByName('online').getChildByName('time').getComponent(cc.Label).string = `${Utils.formatLen(mm, 2)};${Utils.formatLen(ss, 2)}`;
  1444. let fun: Function = () => {
  1445. this.scheduleOnce(() => {
  1446. if (this.isPress) {
  1447. fun();
  1448. }
  1449. else {
  1450. GameDataCenter.tipType = 4;
  1451. UIManager.open('tip:TipPanel');
  1452. // this.onOnline();
  1453. }
  1454. }, 1)
  1455. }
  1456. if (this.onlineTime <= 0) {
  1457. this.ui.getChildByName('online').getChildByName('time').active = false;
  1458. this.ui.getChildByName('online').getChildByName('name').getChildByName('label').getComponent(cc.Label).string = `领取`;
  1459. this.ui.getChildByName('online').getChildByName('name').getChildByName('label').x += 14;
  1460. this.ui.getChildByName('online').getChildByName('name').getChildByName('videoIcon').active = true;
  1461. // this.ui.getChildByName('online').getComponent(cc.Button).interactable = true;
  1462. this.unschedule(this.online);
  1463. Utils.shake(this.ui.getChildByName('online').getChildByName('gift'));
  1464. if (GameDataCenter.gameLevel >= 13) {
  1465. fun();
  1466. }
  1467. }
  1468. }
  1469. /**顶板透明 */
  1470. private topTween(op: number) {
  1471. if (op) {
  1472. this.ui.getChildByName('topPanel').opacity = 255;
  1473. }
  1474. else {
  1475. this.ui.getChildByName('topPanel').opacity = 100;
  1476. }
  1477. }
  1478. //创建数字
  1479. private creatLabel(s: string) {
  1480. let node = new cc.Node();
  1481. node.parent = this.node;
  1482. node.color = cc.color('#f5bf61' as any);
  1483. let label = node.addComponent(cc.Label);
  1484. label.string = s;
  1485. label.fontSize = 34;
  1486. label.lineHeight = 34;
  1487. label.enableBold = true;
  1488. this.scheduleOnce(() => { node.destroy() }, 1);
  1489. }
  1490. }