const { ccclass, property } = cc._decorator; import DirectionType from '../datas/DirectionType'; import CatInfo from '../datas/CatInfo'; import PrefabUtil from '../utils/manager/PrefabUtil'; import GameUtil from '../utils/util/GameUtil'; import UIbase from '../utils/UIbase'; import TipsUI from './TipsUI'; import LocalData from '../manager/LocalData'; import WinUI from './WinUI'; import FailUI from './FailUI'; import PauseUI from './PauseUI'; import StepOverUI from './StepOverUI'; import TimeOverUI from './TimeOverUI'; import Plat from '../utils/Palt'; import AudioPath from '../datas/AudioPath'; import AudioMgr from '../manager/AudioMgr'; @ccclass export default class GameUI extends UIbase { private static _inst: GameUI; public static get inst() { if (this._inst == null) { let v = cc.instantiate(PrefabUtil.get("GameUI")); this._inst = v.getComponent(GameUI); } return this._inst; } @property(cc.Node) catContainer: cc.Node = null; @property(cc.Node) showNode: cc.Node = null; @property(cc.Node) maskNode: cc.Node = null; //遮罩 @property(cc.Node) buttonsNode: cc.Node = null; //按钮组 @property(cc.Node) selectNode: cc.Node = null; //选择视图 @property(cc.Label) timerLabel: cc.Label = null; //计时器 @property(cc.Label) curLevel: cc.Label = null; //关卡 @property(cc.Label) stepLabel: cc.Label = null;//步数计数器 // public grids:Map=new Map(); public grid_num_list: Array = [] public grid_map: Map = new Map(); public cat_info_list: Array = []; public horizontal_count = 20; public vertical_count = 20; public ww = 50; public old_cat_pos: Array = []; public is_game_playing = false; public is_game_pause = false; private stepCount = 0; start() { setInterval(() => { this.onTimerUpdate(); }, 1000); } public resetGameData() { this.grid_num_list = []; this.grid_map = new Map(); this.cat_info_list = []; this.catContainer.removeAllChildren(); this.maskNode.parent = this.catContainer; this.selectNode.active = false } private updateStepStr() { this.stepLabel.string = this.stepCount + "" } public addStepCount() { this.stepCount += 60 this.updateStepStr() this.is_game_playing = true; } private deleteStepCount() { this.stepCount-- this.updateStepStr() if (this.stepCount <= 0) { this.onStepOver() } } public onTimeOver() { this.is_game_playing = false; // FailUI.inst.showUI(); TimeOverUI.inst.showUI() } public onStepOver() { this.is_game_playing = false; StepOverUI.inst.showUI() } public onStartGame() { this.is_game_pause = false; this.resetGameData(); this.showUI(); this.randomCatInfos(); this.updateUI(); this.scheduleOnce(() => { this.checkShow(); }, 0.1) this.curLevel.string = "第 " + LocalData.lv + " 关"; this.updateTimeLabel(); } private setLvData() { let lv = LocalData.lv; if (lv == 1) { this.vertical_count = 6; this.horizontal_count = 6; this.catContainer.scale = 1.5; this.time = 60; } else if (lv == 2) { this.vertical_count = 25; this.horizontal_count = 25; this.catContainer.scale = 1; this.time = 240; } else { this.vertical_count = 25; this.horizontal_count = 25; this.time = 240; this.catContainer.scale = 0.8; } } private dirs: Array = [1, 2, 3, 4]; public randomCatInfos() { this.setLvData(); this.cat_info_list = []; for (let i = 0; i < this.vertical_count; i++) { for (let k = 0; k < this.horizontal_count; k++) { this.grid_num_list.push(i * 10000 + k); this.grid_map.set(i * 10000 + k, 0); } } GameUtil.randomRangeSort(this.grid_num_list); let index = 0; while (true) { if (this.grid_num_list.length == 0) { break; } GameUtil.randomRangeSort(this.dirs); let flag = false; if (GameUtil.randomRange(0, 100) < 50) { for (let i = 0; i < 4; i++) { let id = this.grid_num_list[0]; let id2 = this.getNextGrid(id, this.dirs[i]); if (id2 == -1) { continue; } if (this.grid_map.get(id2) == 1) { continue; } let info = new CatInfo(); info.dir = this.dirs[i]; info.now_grids.push(id); info.now_grids.push(id2); this.grid_map.set(id, 1); this.grid_map.set(id2, 1); GameUtil.deleteValue(this.grid_num_list, id); GameUtil.deleteValue(this.grid_num_list, id2); this.cat_info_list.push(info); flag = true; break; } } if (flag == false) { // console.warn("咋回事呀"); this.grid_num_list.shift(); } index++; if (index > 10000) { break; } } if (LocalData.lv == 1 && this.canAllCatOut() == false) { this.randomCatInfos(); } if (this.cat_info_list.length < 4) { this.randomCatInfos(); } } public getNextGrid(id: number, dir: number) { let i = Math.floor(id / 10000); let k = id % 10000; if (dir == DirectionType.up) { k--; } else if (dir == DirectionType.down) { k++; } else if (dir == DirectionType.left) { i--; } else if (dir == DirectionType.right) { i++; } let val = i * 10000 + k; if (this.grid_map.has(val) == true) { return val; } else { return -1; } } public updateUI() { for (let i = 0; i < this.cat_info_list.length; i++) { let cat = this.getCatNode(this.cat_info_list[i]); cat.parent = this.catContainer; cat.on(cc.Node.EventType.TOUCH_END, this.onClickCatNode, this) this.cat_info_list[i].cat = cat; cat.opacity = 0; } } public getCatNode(info: CatInfo): cc.Node { let node: cc.Node; if (info.cat == null) { node = cc.instantiate(PrefabUtil.get("CatItem")); // console.warn("创建的羊---"+(node)._id) } else { node = info.cat; } let x = Math.floor(info.now_grids[0] / 10000); let y = info.now_grids[0] % 10000; x = (x * this.ww - this.ww / 2 * this.vertical_count) + this.ww / 2; y = (this.ww / 2 * this.horizontal_count - y * this.ww) - this.ww / 2; if (info.dir == DirectionType.up) { y += this.ww / 2; node.angle = 0 } else if (info.dir == DirectionType.down) { y -= this.ww / 2; node.angle = 180 } else if (info.dir == DirectionType.left) { x -= this.ww / 2; node.angle = 90 } else if (info.dir == DirectionType.right) { x += this.ww / 2; node.angle = 270 } node.x = x; node.y = y; return node; } public onClickCatNode(event: cc.Event.EventTouch) { AudioMgr.playSound(AudioPath.SHEEP); if (this.is_game_playing == false) { return; } this.maskNode.active = false; for (let i = 0; i < this.cat_info_list.length; i++) { this.cat_info_list[i].cat.zIndex = 0; } // console.warn("被点击的羊---"+(event.target)._id) for (let i = 0; i < this.cat_info_list.length; i++) { // console.warn("被查询的羊---"+(this.yangs[i].cat)._id) if (this.cat_info_list[i].cat == event.target) { // console.warn(this.yangs[i].grids[0]+"的羊被点击了"); if (this.fz_flag == true) { this.resetDirection2(this.cat_info_list[i]); } else { this.onMoveCat(this.cat_info_list[i]); } return; } } } //检测出来移动位置 public onMoveCat(info: CatInfo) { for (let i = 0; i < info.now_grids.length; i++) { this.grid_map.set(info.now_grids[i], 0); } let i = Math.floor(info.now_grids[0] / 10000); let k = info.now_grids[0] % 10000; if (info.move_tween && info.lastPosition) { info.move_tween.stop() info.cat.x = info.lastPosition.x; info.cat.y = info.lastPosition.y; } info.lastPosition = new cc.Vec2(info.cat.x, info.cat.y) const startX = info.cat.x; const startY = info.cat.y; let add = 0; this.deleteStepCount() if (info.dir == DirectionType.up) { k -= 1; while (true) { add += 1; if (k - add < 0) { add = 100; break; } if (this.grid_map.get(i * 10000 + (k - add)) == 1) { add -= 1; break; } } if (add != 0) { info.push_last(); this.old_cat_pos.push(info); } if (add == 100) { //可以消失 info.move_tween = cc.tween(info.cat) .to(0.1, { y: info.cat.y + 15 }) .to(5, { y: info.cat.y + 2000 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); this.removeCat(info); } else { //碰撞 info.move_tween = cc.tween(info.cat) .to(0.1, { y: info.cat.y + 15 }) .to(0.2 * add, { y: info.cat.y + 15 + this.ww * add }) .delay(0.1) .to(0.1, { y: info.cat.y + 15 + this.ww * add - 15 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); for (let i = 0; i < info.now_grids.length; i++) { let a = Math.floor(info.now_grids[i] / 10000); let b = info.now_grids[i] % 10000; b = b - add; info.now_grids[i] = a * 10000 + b; this.grid_map.set(info.now_grids[i], 1); } } } else if (info.dir == DirectionType.down) { k += 1; while (true) { add += 1; if (k + add >= this.horizontal_count) { add = 100; break; } if (this.grid_map.get(i * 10000 + (k + add)) == 1) { add -= 1; break; } } if (add != 0) { info.push_last(); this.old_cat_pos.push(info); } if (add == 100) { //可以消失 info.move_tween = cc.tween(info.cat) .to(0.1, { y: info.cat.y - 15 }) .to(5, { y: info.cat.y - 2000 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); this.removeCat(info); } else { //碰撞 info.move_tween = cc.tween(info.cat) .to(0.1, { y: info.cat.y - 15 }) .to(0.2 * add, { y: info.cat.y - 15 - this.ww * add }) .delay(0.1) .to(0.1, { y: info.cat.y - 15 - this.ww * add + 15 }) .call(() => { // console.warn("向下移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); for (let i = 0; i < info.now_grids.length; i++) { let a = Math.floor(info.now_grids[i] / 10000); let b = info.now_grids[i] % 10000; b = b + add; info.now_grids[i] = a * 10000 + b; this.grid_map.set(info.now_grids[i], 1); } } } else if (info.dir == DirectionType.left) { i -= 1; while (true) { add += 1; if (i - add < 0) { add = 100; break; } if (this.grid_map.get((i - add) * 10000 + k) == 1) { add -= 1; break; } } if (add != 0) { info.push_last(); this.old_cat_pos.push(info); } if (add == 100) { //可以消失 info.move_tween = cc.tween(info.cat) .to(0.1, { x: info.cat.x - 15 }) .to(5, { x: info.cat.x - 2000 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); this.removeCat(info); } else { //碰撞 info.move_tween = cc.tween(info.cat) .to(0.1, { x: info.cat.x - 15 }) .to(0.2 * add, { x: info.cat.x - 15 - this.ww * add }) .delay(0.1) .to(0.1, { x: info.cat.x - 15 - this.ww * add + 15 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; }) .start(); for (let i = 0; i < info.now_grids.length; i++) { let a = Math.floor(info.now_grids[i] / 10000); let b = info.now_grids[i] % 10000; a = a - add; info.now_grids[i] = a * 10000 + b; this.grid_map.set(info.now_grids[i], 1); } } } else if (info.dir == DirectionType.right) { i += 1; while (true) { add += 1; if (i + add >= this.vertical_count) { add = 100; break; } if (this.grid_map.get((i + add) * 10000 + k) == 1) { add -= 1; break; } } if (add != 0) { info.push_last(); this.old_cat_pos.push(info); } if (add == 100) { //可以消失 info.move_tween = cc.tween(info.cat) .to(0.1, { x: info.cat.x + 15 }) .to(5, { x: info.cat.x + 2000 }) .call(() => { // console.warn("向上移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); this.removeCat(info); } else { //碰撞 info.move_tween = cc.tween(info.cat) .to(0.1, { x: info.cat.x + 15 }) .to(0.2 * add, { x: info.cat.x + 15 + this.ww * add }) .delay(0.1) .to(0.1, { x: info.cat.x + 15 + this.ww * add - 15 }) .call(() => { // console.warn("向下移出完成"); info.move_tween = null; info.lastPosition = null; }) .start(); for (let i = 0; i < info.now_grids.length; i++) { let a = Math.floor(info.now_grids[i] / 10000); let b = info.now_grids[i] % 10000; a = a + add; info.now_grids[i] = a * 10000 + b; this.grid_map.set(info.now_grids[i], 1); } } } } public removeCat(info: CatInfo) { for (let i = 0; i < this.cat_info_list.length; i++) { if (this.cat_info_list[i] == info) { // console.warn("删除的羊---" + (this.cat_info_list[i].cat)._id) this.cat_info_list.splice(i, 1); } } } //检测展示 public checkShow() { let arr = []; let show_fw = this.node.convertToWorldSpaceAR(new cc.Vec2(0, 0)); let up = show_fw.y - this.showNode.height / 2; let down = show_fw.y + this.showNode.height / 2; let left = show_fw.x - this.showNode.width / 2; let right = show_fw.x + this.showNode.width / 2; for (let i = 0; i < this.cat_info_list.length; i++) { let cat = this.cat_info_list[i]; let curr_pos = cat.cat.parent.convertToWorldSpaceAR(cat.cat.position); if (curr_pos.x < left) { arr.push(cat); continue; } if (curr_pos.x > right) { arr.push(cat); continue; } if (curr_pos.y < up) { arr.push(cat); continue; } if (curr_pos.y > down) { arr.push(cat); continue; } } for (let i = 0; i < arr.length; i++) { for (let k = 0; k < this.cat_info_list.length; k++) { if (this.cat_info_list[k] == arr[i]) { this.cat_info_list[k].cat.parent = null; for (let a = 0; a < this.cat_info_list[k].now_grids.length; a++) { this.grid_map.set(this.cat_info_list[k].now_grids[a], 0); } // console.warn("不展示的羊---"+(this.yangs[k].cat)._id) this.cat_info_list.splice(k, 1); break; } } } this.checkDirection(); for (let i = 0; i < this.cat_info_list.length; i++) { let cat = this.cat_info_list[i]; cat.cat.scale = 0; cat.cat.opacity = 255; cc.tween(cat.cat) .delay(GameUtil.randomRange(100, 1500) / 1000) .to(0.5, { scale: 1 }) .start(); } this.is_game_playing = true; this.stepCount = this.cat_info_list.length + 20 this.updateStepStr() } //检测可以跑出去的羊 public chatCatIsOut(): Array { let arr: Array = []; for (let a = 0; a < this.cat_info_list.length; a++) { let info = this.cat_info_list[a]; let i = Math.floor(info.now_grids[0] / 10000); let k = info.now_grids[0] % 10000; if (this.grid_map.get(info.now_grids[0]) == 0) { continue; } let add = 0; if (info.dir == DirectionType.up) { k -= 1; while (true) { add += 1; if (k - add < 0) { add = 100; break; } if (this.grid_map.get(i * 10000 + (k - add)) == 1) { add -= 1; break; } } if (add == 100) { arr.push(info); } } else if (info.dir == DirectionType.down) { k += 1; while (true) { add += 1; if (k + add >= this.horizontal_count) { add = 100; break; } if (this.grid_map.get(i * 10000 + (k + add)) == 1) { add -= 1; break; } } if (add == 100) { arr.push(info); } } else if (info.dir == DirectionType.left) { i -= 1; while (true) { add += 1; if (i - add < 0) { add = 100; break; } if (this.grid_map.get((i - add) * 10000 + k) == 1) { add -= 1; break; } } if (add == 100) { arr.push(info); } } else if (info.dir == DirectionType.right) { i += 1; while (true) { add += 1; if (i + add >= this.vertical_count) { add = 100; break; } if (this.grid_map.get((i + add) * 10000 + k) == 1) { add -= 1; break; } } if (add == 100) { arr.push(info); } } } return arr; } public canAllCatOut() { let jilu: Array = []; while (true) { let aa = this.chatCatIsOut(); if (aa.length == 0) { // console.error("不可全部消除"); break; } for (let i = 0; i < aa.length; i++) { for (let k = 0; k < aa[i].now_grids.length; k++) { jilu.push(aa[i].now_grids[k]); this.grid_map.set(aa[i].now_grids[k], 0); } } if (jilu.length == this.cat_info_list.length * 2) { // console.error("可以全部消除") for (let i = 0; i < jilu.length; i++) { this.grid_map.set(jilu[i], 1); } return true; } } return false; } //撤回 public onClickRevoke() { this.is_game_playing = false Plat.showRewardVideo((success: boolean) => { this.is_game_playing = true; if (success) { if (this.old_cat_pos.length == 0) { TipsUI.inst.showTips("没有可撤回的操作"); return; } let info = this.old_cat_pos.pop(); if (info.move_tween != null) { info.move_tween.stop(); } for (let i = 0; i < info.now_grids.length; i++) { this.grid_map.set(info.now_grids[i], 0); } info.revoke(); for (let i = 0; i < info.now_grids.length; i++) { this.grid_map.set(info.now_grids[i], 1); } info.cat = this.getCatNode(info); if (this.cat_info_list.indexOf(info) == -1) { this.cat_info_list.push(info); } } }) } //高亮 public onClickLightCat() { this.is_game_playing = false; Plat.showRewardVideo((success: boolean) => { this.is_game_playing = true; if (success) { let arr = this.chatCatIsOut(); if (arr.length == 0) { TipsUI.inst.showTips("没有可消除的动物"); return; } this.maskNode.active = true; this.maskNode.zIndex = 99; for (let i = 0; i < arr.length; i++) { arr[i].cat.zIndex = 100; } } }) } public fz_flag = false; public onClickResetDirection() { this.is_game_playing = false Plat.showRewardVideo((success: boolean) => { this.is_game_playing = true if (success) { if (this.cat_info_list.length == 0) { return; } this.buttonsNode.active = false; this.fz_flag = true; this.selectNode.active = true; for (let i = 0; i < this.cat_info_list.length; i++) { this.cat_info_list[i].cat.zIndex = 100; } } }) } public onClickAddTime() { this.time += 60; this.updateTimeLabel(); this.is_game_playing = true } public resetDirection2(info: CatInfo) { if (this.cat_info_list.length == 0) { return; } this.buttonsNode.active = true; this.fz_flag = false; this.selectNode.active = false; this.resetDirection3(info); } public resetDirection3(info: CatInfo) { info.dir = (info.dir - 1 + 2) % 4 + 1; info.now_grids.reverse(); info.cat = this.getCatNode(info); } public time = 240; private onTimerUpdate() { if (this.is_game_playing == false) { return; } if (this.is_game_pause == true) { return; } this.time--; if (this.time < 0) { //游戏失败 this.is_game_playing = false; setTimeout(() => { // FailUI.inst.showUI(); this.onTimeOver() }, 1000); //弹窗 return; } this.updateTimeLabel(); } public updateTimeLabel() { let tt = Math.floor(this.time / 60); let ss = this.time % 60; this.timerLabel.string = "0" + tt + ":" + (ss < 10 ? "0" + ss : ss); } private checkDirection() { let map: Map> = new Map(); let map2: Map> = new Map(); for (let i = 0; i < this.cat_info_list.length; i++) { let info = this.cat_info_list[i]; if (info.dir == DirectionType.left || info.dir == DirectionType.right) { let g = Math.floor(info.now_grids[0] % 10000); if (info.dir == DirectionType.right) { this.resetDirection3(info); } if (map.has(g) == false) { map.set(g, new Array()); } map.get(g).push(info); } else { if (info.dir == DirectionType.down) { this.resetDirection3(info); } let g = Math.floor(info.now_grids[0] / 10000); if (map2.has(g) == false) { map2.set(g, new Array()); } map2.get(g).push(info); } } map.forEach((val: Array, key) => { val.sort((v1, v2) => { let a1 = Math.floor(v1.now_grids[0] / 10000); let a2 = Math.floor(v2.now_grids[0] / 10000); return a1 - a2; }) let index = GameUtil.randomRange(0, val.length + 1); for (let i = index; i < val.length; i++) { this.resetDirection3(val[i]); } }); map2.forEach((val: Array, key) => { val.sort((v1, v2) => { let a1 = Math.floor(v1.now_grids[0] % 10000); let a2 = Math.floor(v2.now_grids[0] % 10000); return a1 - a2; }) let index = GameUtil.randomRange(0, val.length + 1); for (let i = index; i < val.length; i++) { this.resetDirection3(val[i]); } }); } public update() { if (this.is_game_playing == true) { if (this.cat_info_list.length == 0) { this.is_game_playing = false; this.onGameOver(); } } } private onGameOver() { LocalData.lv++; setTimeout(() => { AudioMgr.playSound(AudioPath.LEVELUP); WinUI.inst.showUI(); }, 1000); } public onClickPause() { this.is_game_pause = true; AudioMgr.playSound(AudioPath.CLICK); PauseUI.inst.showUI(); } }