game.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /**
  2. * @author uu
  3. * @file 游戏控制
  4. */
  5. var AC = require('action')
  6. const ADSdk = require('ADSdk');
  7. var HTTPS = require('./ts/HTTPS').HTTPSIns
  8. var NetPost = require('./ts/HTTPS').NetPost
  9. cc.Class({
  10. extends: cc.Component,
  11. properties: {
  12. _status: 0, //0 未开始 1 游戏开始 2 游戏暂停 3 游戏结束 4 下落状态 5无法触摸状态
  13. blockPrefab: cc.Prefab,
  14. blockSprite: [cc.SpriteFrame], //todo: 换成动态生成 暂不处理
  15. warningSpriteFrame: [cc.SpriteFrame],
  16. propSpriteFrame: [cc.SpriteFrame],
  17. checkMgr: require("check"),
  18. revivePage: cc.Node,
  19. tutorialNode: cc.Node,
  20. shareBtn: cc.Node,
  21. shareSuccessDialog: cc.Node,
  22. redBtnSprite: cc.Sprite,
  23. redBtnSpriteFrame: [cc.SpriteFrame],
  24. moneyLabel: cc.Label,
  25. redBagIcon: cc.Prefab,
  26. signInBtn: cc.Node,
  27. // bombAddLabel:cc.Label,
  28. // btnLabel:cc.Label,
  29. },
  30. start() {
  31. this.showRedBtn();
  32. this.showSignInBtn();
  33. this.bindNode()
  34. this.generatePool()
  35. this.loadRes()
  36. // this.btnLabel.string = "确定";
  37. // this.bombAddLabel.string = "炸弹+1";
  38. },
  39. showRedBtn() {
  40. if (Utils.hadRedPacket()) {
  41. this.redBtnSprite.spriteFrame = this.redBtnSpriteFrame[1];
  42. this.moneyLabel.node.active = false
  43. } else {
  44. this.redBtnSprite.spriteFrame = this.redBtnSpriteFrame[0];
  45. this.moneyLabel.node.active = true;
  46. let moneyNum = Utils.getRedPacketNum();
  47. if (moneyNum == 0) moneyNum = "0.00";
  48. this.moneyLabel.string = moneyNum + "元";
  49. }
  50. },
  51. showSignInBtn() {
  52. if (Utils.isSecondDay()) {
  53. Utils.clearSignIn();
  54. }
  55. if (Utils.hadSignIn()) {
  56. this.signInBtn.active = false;
  57. } else {
  58. this.signInBtn.active = true;
  59. }
  60. },
  61. closeRedUIAni() {
  62. let btn = this.redBtnSprite.node;
  63. let position = btn.convertToWorldSpaceAR(cc.v2(0, 0));// btn转世界坐标
  64. position = this.node.convertToNodeSpaceAR(position);// 世界坐标转game节点下坐标
  65. let node = cc.instantiate(this.redBagIcon);
  66. node.parent = this.node;
  67. node.runAction(
  68. cc.sequence(
  69. cc.moveTo(0.5, position),
  70. cc.scaleTo(0.3, 1, 1),
  71. cc.callFunc(() => { node.destroy(); })
  72. ));
  73. },
  74. loadRes() {
  75. },
  76. init(c) {
  77. this._controller = c
  78. this._score = c.scoreMgr
  79. this.rowNum = c.config.json.rowNum
  80. this.gap = c.config.json.gap
  81. this.animationSpeed = c.config.json.gap
  82. this.blockWidth = (730 - (this.rowNum + 1) * this.gap) / this.rowNum
  83. this.reviveTimer = null
  84. this.tutorialNode.active = false
  85. // this.isWeChat = this._controller.social.node.active
  86. this.shareSuccessDialog.active = false
  87. //console.log(this.gap)
  88. //console.log(this.blockWidth)
  89. },
  90. showBanner() {
  91. },
  92. // 动态获取需要动态控制的组件
  93. bindNode() {
  94. this.blocksContainer = this.node.getChildByName('map')
  95. },
  96. //---------------- 游戏控制 ---------------------
  97. // 游戏开始
  98. gameStart() {
  99. this.recoveryAllBlocks().then()
  100. this.shareBtn.active = true
  101. // if (this.isWeChat) {
  102. // this._controller.social.hasShared = false
  103. // }
  104. this._score.init(this)
  105. let data = [
  106. [1, 1, 1, 1, 1, 1, 1, 1],
  107. [1, 1, 1, 1, 1, 1, 1, 1],
  108. [4, 2, 3, 4, 2, 2, 3, 4]
  109. ]
  110. if (this.isFirstTime()) {
  111. this.mapSet(this.rowNum, data).then((result) => {
  112. this.showTutorial(this.map[1][4], '点击连续的区域生成炸弹鸭')
  113. this.tutorialProgress = 1
  114. this._status = 1
  115. })
  116. } else {
  117. this.mapSet(this.rowNum).then((result) => {
  118. this._status = 1
  119. })
  120. }
  121. },
  122. showTutorial(target, label) {
  123. this.tutorialNode.active = true
  124. this.tutorialNode.getChildByName('targetBtn').getChildByName('sqr').runAction(cc.repeatForever(cc.sequence(cc.scaleTo(0.3, 0.8), cc.scaleTo(0.3, 1.2))))
  125. this.tutorialNode.getChildByName('target').x = target.x
  126. this.tutorialNode.getChildByName('target').y = target.y
  127. this.tutorialNode.getChildByName('targetBtn').x = target.x
  128. this.tutorialNode.getChildByName('targetBtn').y = target.y
  129. this.tutorialNode.getChildByName('label').getChildByName('label').getComponent(cc.Label).string = label
  130. },
  131. closeTutorial() {
  132. this.tutorialNode.getChildByName('targetBtn').getChildByName('sqr').stopAllActions()
  133. // console.log('close Tutorial ')
  134. this.tutorialNode.active = false
  135. this._status = 1
  136. this.map[1][4].getComponent('cell').onTouched({
  137. type: 1
  138. }, false, false)
  139. if (this.tutorialProgress == 1) {
  140. setTimeout(() => {
  141. this.showTutorial(this.map[1][4], '点击炸弹消除所有同色方块哦')
  142. this.tutorialProgress = 2
  143. }, 1000)
  144. }
  145. },
  146. isFirstTime() {
  147. let isFirst = false
  148. if (this.isWeChat && !wx.getStorageSync('isFirst')) {
  149. wx.setStorageSync('isFirst', "1")
  150. isFirst = true
  151. } else if (!cc.sys.localStorage.getItem('isFirst')) {
  152. cc.sys.localStorage.setItem('isFirst', "1")
  153. isFirst = true
  154. }
  155. return isFirst
  156. },
  157. onItemShare() {
  158. // if (this.isWeChat) {
  159. // this._controller.social.onItemShareButton()
  160. // } else {
  161. this.fakeShareSuccess()
  162. // }
  163. },
  164. onItemAdv() {
  165. // TODO 广告 视频炸弹
  166. if (AppConst.SHOWADUI) {
  167. if (AppConst.CHANNEL == AppConst.channel.ANDROID) {
  168. ADSdk.pay(1, this);
  169. } else {
  170. ADSdk.showVideo(null, (result) => {
  171. if (result == 1) {
  172. this.fakeShareSuccess()
  173. }
  174. });
  175. }
  176. } else {
  177. this.fakeShareSuccess()
  178. }
  179. // this.fakeShareSuccess()
  180. // self._controller.scoreMgr.onLevelUpButton()
  181. },
  182. fakeShareSuccess() {
  183. this.shareBtn.active = false
  184. this.shareSuccessDialog.active = true
  185. // 2分钟后再次弹出 炸弹按钮
  186. this.scheduleOnce(() => {
  187. this.shareBtn.active = true;
  188. }, 120);
  189. },
  190. onCreateBomb() {
  191. let x = Math.floor(Math.random() * 8)
  192. let y = Math.floor(Math.random() * 8)
  193. this.shareSuccessDialog.active = false
  194. if (this.map[x][y].getComponent('cell')._itemType == 0) {
  195. this.map[x][y].getComponent('cell').changeItemType(2)
  196. } else {
  197. this.onCreateBomb()
  198. return
  199. }
  200. },
  201. /**
  202. * 初始化地图
  203. * @param {*} num
  204. * @param {*} data 传入颜色数组
  205. */
  206. mapSet(num, data) {
  207. this.map = new Array()
  208. let self = this
  209. // 生成两个随机的对象数组
  210. let a = Math.floor(Math.random() * num)
  211. let b = Math.floor(Math.random() * num)
  212. let c = Math.floor(1 + Math.random() * (num - 1)) - 1
  213. a == c ? c++ : ''
  214. let d = Math.floor(Math.random() * num)
  215. this.tutorialPos = [c, d]
  216. return new Promise((resolve, reject) => {
  217. for (let i = 0; i < num; i++) { //行
  218. this.map[i] = new Array()
  219. for (let j = 0; j < num; j++) { //列
  220. let itemType = (i == a && j == b) ? 1 : (i == c && j == d) ? (data ? 1 : 2) : 0
  221. self.map[i][j] = self.instantiateBlock(self, {
  222. x: j,
  223. y: i,
  224. color: (data && data[i]) ? data[i][j] : null,
  225. width: self.blockWidth,
  226. startTime: (i + j + 1) * self._controller.config.json.startAnimationTime / num * 2
  227. }, self.blocksContainer, itemType)
  228. }
  229. }
  230. this.checkMgr.init(this)
  231. setTimeout(() => {
  232. resolve('200 OK');
  233. this.checkMgr.check(this)
  234. }, self._controller.config.json.startAnimationTime * num / 2 / 1
  235. // (cc.game.getFrameRate() / 60)
  236. )
  237. })
  238. },
  239. //防抖动 判断是否需要检测下落
  240. checkNeedFall() {
  241. if (this.checkNeedFallTimer) {
  242. clearTimeout(this.checkNeedFallTimer)
  243. }
  244. this.checkNeedFallTimer = setTimeout(() => {
  245. if (this._status == 5) {
  246. this._status = 4
  247. this.onFall()
  248. }
  249. }, 300 / 1
  250. // (cc.game.getFrameRate() / 60)
  251. )
  252. },
  253. //方块下落
  254. onFall() {
  255. this.checkGenerateProp(this._score.chain).then(() => {
  256. let self = this
  257. let canFall = 0
  258. //从每一列的最下面一个开始往上判断
  259. //如果有空 就判断有几个空 然后让最上方的方块掉落下来
  260. for (let j = this.rowNum - 1; j >= 0; j--) {
  261. canFall = 0
  262. for (let i = this.rowNum - 1; i >= 0; i--) {
  263. if (this.map[i][j].getComponent('cell')._status == 2) {
  264. this.blockPool.put(this.map[i][j])
  265. this.map[i][j] = null
  266. canFall++
  267. } else {
  268. if (canFall != 0) {
  269. this.map[i + canFall][j] = this.map[i][j]
  270. this.map[i][j] = null
  271. this.map[i + canFall][j].getComponent('cell').playFallAction(canFall, {
  272. x: j,
  273. y: i + canFall,
  274. })
  275. }
  276. }
  277. }
  278. for (var k = 0; k < canFall; k++) {
  279. this.map[k][j] = this.instantiateBlock(this, {
  280. x: j,
  281. y: k,
  282. width: this.blockWidth,
  283. startTime: null
  284. }, this.blocksContainer, '', {
  285. x: j,
  286. y: -canFall + k
  287. })
  288. this.map[k][j].getComponent('cell').playFallAction(canFall, null)
  289. }
  290. }
  291. setTimeout(() => {
  292. this.checkMgr.init(this)
  293. this.checkMgr.check(this)
  294. this._status = 1
  295. }, 250)
  296. })
  297. },
  298. gameOver() {
  299. this._status = 3
  300. this._controller.pageMgr.addPage(2)
  301. this._controller.pageMgr.addPage(4)
  302. // 游戏结束 banner或者广告
  303. // if (this._controller.social.node.active) {
  304. // this._controller.social.closeBannerAdv()
  305. // }
  306. },
  307. // todo 复活
  308. askRevive() {
  309. this._controller.pageMgr.addPage(2)
  310. this._controller.pageMgr.addPage(5)
  311. this.revivePage.active = true
  312. this.revivePage.getChildByName('askRevive').active = true
  313. this.revivePage.getChildByName('successRevive').active = false
  314. this.rangeSprite = this.revivePage.getChildByName('askRevive').getChildByName('numBg').getChildByName('sprite').getComponent(cc.Sprite)
  315. this.rangeSprite.fillRange = 1
  316. this.isRangeAction = true
  317. let numLabel = this.revivePage.getChildByName('askRevive').getChildByName('numBg').getChildByName('num').getComponent(cc.Label)
  318. numLabel.string = 9
  319. if (this.reviveTimer) {
  320. clearInterval(this.reviveTimer)
  321. }
  322. this.reviveTimer = setInterval(() => {
  323. if (+numLabel.string > 0) {
  324. numLabel.string--
  325. this.rangeSprite.fillRange = 1
  326. } else {
  327. this.onSkipRevive()
  328. }
  329. }, 1000)
  330. },
  331. onReviveButton() {
  332. clearInterval(this.reviveTimer)
  333. this.isRangeAction = false
  334. let Tips = cc.Canvas.instance.node.getChildByName("Tips")
  335. let TipsComp = Tips.getComponent('Tips')
  336. let now = cc.sys.now()
  337. sdk.showVideoAd(() => {
  338. this.showReviveSuccess()
  339. HTTPS.post(NetPost.record, {
  340. ad_type: 'reward',//广告类型(默认reward)
  341. duration: (cc.sys.now() - now) / 1000,//观看时长,单位秒(默认30)
  342. }).then(res => {
  343. if (res.code != 200) {
  344. TipsComp.show(res.msg)
  345. return
  346. }
  347. })
  348. now = 0
  349. }, () => {
  350. now = 0
  351. })
  352. return
  353. // TODO 广告 视频复活
  354. if (AppConst.SHOWADUI) {
  355. if (AppConst.CHANNEL == AppConst.channel.ANDROID) {
  356. ADSdk.pay(2, this);
  357. } else {
  358. ADSdk.showVideo(null, (result) => {
  359. if (result == 1) {
  360. this.showReviveSuccess()
  361. }
  362. });
  363. }
  364. } else {
  365. this.showReviveSuccess()
  366. }
  367. // this.showReviveSuccess()
  368. // self._controller.game.onSkipRevive()
  369. },
  370. showReviveSuccess() {
  371. //console.log('打开复活成功页面')
  372. this.revivePage.getChildByName('askRevive').active = false
  373. this.revivePage.getChildByName('successRevive').active = true
  374. },
  375. onReviveCertainBtn() {
  376. this._controller.pageMgr.removePage(2)
  377. this.revivePage.active = false
  378. this._status = 1
  379. this._score.onRevive()
  380. },
  381. update() {
  382. if (this.isRangeAction) {
  383. this.rangeSprite.fillRange -= 1 / 60
  384. }
  385. },
  386. onSkipRevive() {
  387. clearInterval(this.reviveTimer)
  388. this._controller.pageMgr.pages[5].active = false
  389. this._score.onGameOver(true)
  390. this.isRangeAction = false
  391. },
  392. restart() {
  393. this._controller.pageMgr.onOpenPage(1)
  394. this.recoveryAllBlocks().then(() => {
  395. this.gameStart()
  396. })
  397. },
  398. // -----------------道具相关---------------
  399. // 储存用户点击时的方块 用于生成道具
  400. onUserTouched(iid, jid, itemType, color, warning, pos) {
  401. this.target = {
  402. i: iid,
  403. j: jid,
  404. color: color,
  405. itemType: itemType,
  406. x: pos.x,
  407. y: pos.y,
  408. warning: warning
  409. }
  410. },
  411. // 生成道具 type 1为双倍倍数 2为炸弹 3为加五百
  412. generatePropItem(type) {
  413. return new Promise((resolve, reject) => {
  414. // 是否做道具生成动画
  415. this.map[this.target.i][this.target.j] = this.instantiateBlock(this, {
  416. x: this.target.j,
  417. y: this.target.i,
  418. color: this.target.color,
  419. width: this.blockWidth,
  420. startTime: null
  421. }, this.blocksContainer, type)
  422. setTimeout(() => {
  423. resolve()
  424. }, 300)
  425. })
  426. },
  427. checkGenerateProp(chain) {
  428. return new Promise((resolve, reject) => {
  429. if (this.target && this.target.warning) {
  430. this.generatePropItem(this.target.warning).then(() => {
  431. resolve()
  432. return
  433. })
  434. }
  435. resolve()
  436. })
  437. },
  438. onItem(type, color, pos) {
  439. switch (type) {
  440. case 1:
  441. // 分数翻倍 最高八倍
  442. this._score.tipBox.init(this._score, 1)
  443. this._score.addMult(color, pos)
  444. this._controller.musicMgr.onDouble()
  445. for (let i = 0; i < this.rowNum; i++) { //行
  446. for (let j = 0; j < this.rowNum; j++) { //列
  447. if (this.map[i][j] && this.map[i][j].getComponent('cell')._status == 1) {
  448. let distance = Math.sqrt(Math.pow(pos.x - this.map[i][j].x, 2) + Math.pow(pos.y - this.map[i][j].y, 2))
  449. if (distance != 0) {
  450. this.map[i][j].getComponent('cell').surfaceAction(distance)
  451. }
  452. }
  453. }
  454. }
  455. break
  456. case 2:
  457. // 炸弹 消除同种颜色的
  458. this._score.tipBox.init(this._score, 2)
  459. this.node.runAction(AC.shackAction(0.1, 10))
  460. // 震动
  461. // if (this._controller.social.node.active) {
  462. // this._controller.social.onShakePhone()
  463. // }
  464. this.isPropChain = true
  465. this._controller.musicMgr.onBoom()
  466. for (let i = 0; i < this.rowNum; i++) { //行
  467. for (let j = 0; j < this.rowNum; j++) { //列
  468. if (this.map[i][j] && this.map[i][j].getComponent('cell').color == color && this.map[i][j] && this.map[i][j].getComponent('cell')._status != 2) {
  469. this.map[i][j].getComponent('cell').onTouched(color, false, true)
  470. } else {
  471. this.map[i][j].runAction(AC.rockAction(0.2, 10))
  472. }
  473. }
  474. }
  475. break
  476. case 3: //: 加步数
  477. this._score.tipBox.init(this._score, 4)
  478. this._controller.musicMgr.onDouble()
  479. for (let i = 0; i < this.rowNum; i++) { //行
  480. for (let j = 0; j < this.rowNum; j++) { //列
  481. if (this.map[i][j] && this.map[i][j].getComponent('cell')._status == 1) {
  482. let distance = Math.sqrt(Math.pow(pos.x - this.map[i][j].x, 2) + Math.pow(pos.y - this.map[i][j].y, 2))
  483. if (distance != 0) {
  484. this.map[i][j].getComponent('cell').surfaceAction(distance)
  485. }
  486. }
  487. }
  488. }
  489. this._score.onStep(3).then()
  490. break;
  491. case 4: // : 消除全部单身的方块
  492. this._score.tipBox.init(this._score, 5)
  493. this.isPropChain = true
  494. this._controller.musicMgr.onMagic()
  495. for (let i = 0; i < this.rowNum; i++) { //行
  496. for (let j = 0; j < this.rowNum; j++) { //列
  497. if (this.map[i][j] && this.map[i][j].getComponent('cell').isSingle && this.map[i][j] && this.map[i][j].getComponent('cell')._status != 2) {
  498. let distance = Math.sqrt(Math.pow(pos.x - this.map[i][j].x, 2) + Math.pow(pos.y - this.map[i][j].y, 2))
  499. this.map[i][j].getComponent('cell').onTouched(color, false, true, distance)
  500. // console.log("魔法棒触发的点", i, j, this.map[i][j].getComponent('cell').color, this.map[i][j].getComponent('cell').isSingle)
  501. }
  502. }
  503. }
  504. break;
  505. }
  506. },
  507. //--------------------- 预制体实例化---------------------
  508. // 生成对象池
  509. generatePool() {
  510. this.blockPool = new cc.NodePool()
  511. for (let i = 0; i < Math.pow(this.rowNum, 2); i++) {
  512. let block = cc.instantiate(this.blockPrefab)
  513. this.blockPool.put(block)
  514. }
  515. },
  516. // 实例化单个方块
  517. instantiateBlock(self, data, parent, itemType, pos) {
  518. itemType = itemType ? itemType : 0
  519. if (itemType != 0) {
  520. // console.log("道具节点数据", data, itemType)
  521. }
  522. let block = null
  523. if (self.blockPool && self.blockPool.size() > 0) {
  524. block = self.blockPool.get()
  525. } else {
  526. block = cc.instantiate(self.blockPrefab)
  527. }
  528. block.parent = parent
  529. block.scale = 1
  530. block.x = 0
  531. block.y = 0
  532. block.getComponent('cell').init(self, data, this.blockWidth, itemType, pos)
  533. return block
  534. },
  535. // 回收所有节点
  536. recoveryAllBlocks() {
  537. return new Promise((resolve, reject) => {
  538. let children = this.blocksContainer.children
  539. if (children.length != 0) {
  540. let length = children.length
  541. // console.log(length)
  542. for (let i = 0; i < length; i++) {
  543. this.blockPool.put(children[0])
  544. }
  545. for (let i = 0; i < this.rowNum; i++) {
  546. for (let j = 0; j < this.rowNum; j++) {
  547. this.map[i][j] = null
  548. }
  549. }
  550. }
  551. resolve('')
  552. })
  553. },
  554. });