|
|
@@ -1,921 +0,0 @@
|
|
|
-import { _decorator, Component, Node, find, assetManager, JsonAsset, Prefab, UITransform, Widget, Vec3, instantiate, Sprite, randomRangeInt, EventTouch, Vec2, tween, Label, Color } from 'cc'
|
|
|
-import { oops } from 'db://oops-framework/core/Oops';
|
|
|
-import { ecs } from 'db://oops-framework/libs/ecs/ECS';
|
|
|
-import { CCComp } from 'db://oops-framework/module/common/CCComp';
|
|
|
-import { GameComponent } from 'db://oops-framework/module/common/GameComponent';
|
|
|
-const { ccclass, property } = _decorator;
|
|
|
-
|
|
|
-export enum GameStatus {
|
|
|
- init, //初始化
|
|
|
- running, //运行中
|
|
|
- end, //结束
|
|
|
- pass //通关
|
|
|
-}
|
|
|
-
|
|
|
-enum GridStatus {
|
|
|
- notUse,
|
|
|
- used,
|
|
|
-}
|
|
|
-
|
|
|
-interface GridDataInterface {
|
|
|
- name: string,
|
|
|
- status: GridStatus,
|
|
|
- gridNode: Node | null,
|
|
|
- row: number,
|
|
|
- column: number,
|
|
|
- gridColorKey: string | null,
|
|
|
- gridType: number, //代替gridColorKey
|
|
|
-}
|
|
|
-
|
|
|
-interface GridConfigDataInterface {
|
|
|
- row: number,
|
|
|
- column: number,
|
|
|
-}
|
|
|
-
|
|
|
-interface BrickDataInterface {
|
|
|
- index: number,
|
|
|
- brickKey: string,
|
|
|
- rotateFlag: boolean,
|
|
|
- gridConfig: GridConfigDataInterface[],
|
|
|
- deg: number,
|
|
|
- brickNode: Node | null,
|
|
|
- gridColorKey: string,
|
|
|
- brickInitPos: Vec3 | null,
|
|
|
- rotateNode: Node | null,
|
|
|
- gridType: number, //gridColorKey
|
|
|
-}
|
|
|
-
|
|
|
-interface EditingDataInterface {
|
|
|
- brickData: BrickDataInterface,
|
|
|
- gridList: GridDataInterface[],
|
|
|
-}
|
|
|
-
|
|
|
-@ccclass('GameView')
|
|
|
-export class GameView extends GameComponent {
|
|
|
-
|
|
|
- row = 8
|
|
|
- column = 8
|
|
|
- gridSize = 76.25
|
|
|
- gridMargin = 1
|
|
|
- brickNum = 3
|
|
|
- yOffset = 100
|
|
|
- aniBrickMove = 0.15 //动画时长
|
|
|
- aniBrickRotate = 0.1 //
|
|
|
- aniBrickEliminate = 0.2
|
|
|
-
|
|
|
- notUseColor = new Color(255, 255, 255, 255)
|
|
|
- usableColor = new Color(0, 255, 0, 100)
|
|
|
- unavailableColor = new Color(255, 0, 0, 100)
|
|
|
- rotateFaultTolerant = 10
|
|
|
-
|
|
|
- bundleName = 'movebrick'
|
|
|
- gameConfig = {}
|
|
|
- gameStatus = GameStatus.init
|
|
|
- _score = 0
|
|
|
- editingData: EditingDataInterface = {
|
|
|
- brickData: null!,
|
|
|
- gridList: [],
|
|
|
- } //修改的数据
|
|
|
- gridList: GridDataInterface[][] = []
|
|
|
- bricksList: BrickDataInterface[] = []
|
|
|
- gridColorList: GridDataInterface[] = []
|
|
|
- deltaTime: number = 1
|
|
|
- operateFlag = false
|
|
|
- touchStartPos = new Vec2()
|
|
|
- adShowingFlag = false
|
|
|
-
|
|
|
- canvasNode: Node = null!
|
|
|
- gridsNode: Node = null! //网格层
|
|
|
- bricksNode: Node = null! //底部方块
|
|
|
- movingNode: Node = null! //移动层
|
|
|
- rotateContainer: Node = null! //旋转层
|
|
|
- scoreLabel: Label = null!
|
|
|
- gameOverPopupNode: Node = null!
|
|
|
-
|
|
|
- gridPrefab: Prefab = null! //空格子预制体
|
|
|
- rotatePrefab: Prefab = null! //旋转预制体
|
|
|
- prefabUrlMap = {} //格子预制体 //所有的格子预制体
|
|
|
-
|
|
|
- //游戏新增的
|
|
|
- @property([Prefab]) //所有的预制体,代替prefabUrlMap
|
|
|
- allBrickList: any[] = [];
|
|
|
- Lab_target: Label = null! //目标分数
|
|
|
- brickListConfig: { bricks?: any } = {} //方块配置
|
|
|
- @property(Prefab)
|
|
|
- gridPb: Prefab = null! //空格子预制体
|
|
|
- @property({ type: Prefab, displayName: "旋转标志" })
|
|
|
- rotatePb: Prefab = null! //空格子预制体
|
|
|
-
|
|
|
-
|
|
|
- get score() {
|
|
|
- return this._score
|
|
|
- }
|
|
|
-
|
|
|
- set score(v: number) {
|
|
|
- this._score = v
|
|
|
- this.scoreLabel.string = `${this.score}`
|
|
|
- }
|
|
|
-
|
|
|
- setAdShowingFlag(v: boolean) {
|
|
|
- this.adShowingFlag = v
|
|
|
- // 打开激励视频时暂停背景音乐
|
|
|
-
|
|
|
- }
|
|
|
- onLoad() {
|
|
|
-
|
|
|
- this.gridsNode = this.node.getChildByPath('Scene/Center/gridNode')!
|
|
|
- this.bricksNode = this.node.getChildByPath('Scene/Bottom/bricksNode')!
|
|
|
- this.movingNode = this.node.getChildByPath('Scene/moveNode')!
|
|
|
- this.rotateContainer = this.node.getChildByPath('Scene/rotateNode')!
|
|
|
- const scoreNode = this.node.getChildByPath('Scene/Top/scoreNode/lab_score')
|
|
|
- if (!scoreNode) {
|
|
|
- console.error('Score node not found')
|
|
|
- return
|
|
|
- }
|
|
|
- const label = scoreNode.getComponent(Label)
|
|
|
- if (!label) {
|
|
|
- console.error('Label component not found on score node')
|
|
|
- return
|
|
|
- }
|
|
|
- this.scoreLabel = label
|
|
|
- }
|
|
|
-
|
|
|
- start() {
|
|
|
- // 模拟延时
|
|
|
- this.scheduleOnce(() => {
|
|
|
- this.loadGameConfig().then(() => {
|
|
|
- // 生成游戏网格
|
|
|
- this.generateGrids()
|
|
|
- this.scheduleOnce(() => {
|
|
|
- this.initData()
|
|
|
- })
|
|
|
- })
|
|
|
- }, 1)
|
|
|
- }
|
|
|
-
|
|
|
- loadGameConfig() {
|
|
|
- let json_name: string = "gui/eliminate/config/GridConfig";
|
|
|
- return new Promise<void>((resolve, reject) => {
|
|
|
- oops.res.load(json_name, JsonAsset, (err: Error | null, res: any) => {
|
|
|
- if (res) {
|
|
|
- this.brickListConfig = res.json;
|
|
|
- resolve();
|
|
|
- } else {
|
|
|
- console.log("JSON数据加载失,请检查文件");
|
|
|
- reject(err);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- setGameStauts(stauts: GameStatus) {
|
|
|
- if (stauts === this.gameStatus) return
|
|
|
- this.gameStatus = stauts
|
|
|
- if (this.gameStatus === GameStatus.init) {
|
|
|
- // this.gameOverPopupNode.active = false
|
|
|
- }
|
|
|
- else if (this.gameStatus === GameStatus.running) {
|
|
|
- // this.gameOverPopupNode.active = false
|
|
|
- }
|
|
|
- else if (this.gameStatus === GameStatus.end) {
|
|
|
- // this.gameOverPopupNode.active = true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- initData() {
|
|
|
- this.setGameStauts(GameStatus.init)
|
|
|
- this.score = 0
|
|
|
- this.gridColorList.length = 0
|
|
|
- this.operateFlag = false
|
|
|
- this.adShowingFlag = false
|
|
|
- this.touchStartPos.set(Vec2.ZERO)
|
|
|
- this.rotateContainer.destroyAllChildren()
|
|
|
- // 初始化格子状态
|
|
|
- for (let rowIndex = 0; rowIndex < this.row; rowIndex++) {
|
|
|
- for (let columnIndex = 0; columnIndex < this.column; columnIndex++) {
|
|
|
- this.gridList[rowIndex][columnIndex].status = GridStatus.notUse
|
|
|
- this.generateGrid(this.gridList[rowIndex][columnIndex])
|
|
|
- }
|
|
|
- }
|
|
|
- // 初始化方块
|
|
|
- this.bricksNode.destroyAllChildren()
|
|
|
- this.bricksList.length = 0
|
|
|
- for (let i = 1; i <= this.brickNum; i++) {
|
|
|
- this.addBrick(i)
|
|
|
- }
|
|
|
-
|
|
|
- this.setGameStauts(GameStatus.running)
|
|
|
- this.operateFlag = true
|
|
|
- }
|
|
|
-
|
|
|
- generateGrids() {
|
|
|
- this.gridsNode.destroyAllChildren()
|
|
|
- const transform = this.gridsNode.getComponent(UITransform)
|
|
|
- if (transform) {
|
|
|
- transform.setContentSize(
|
|
|
- this.gridSize * this.column + this.gridMargin * 2,
|
|
|
- this.gridSize * this.row + this.gridMargin * 2,
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- for (let rowIndex = 0; rowIndex < this.row; rowIndex++) {
|
|
|
- this.gridList.push([])
|
|
|
- for (let columnIndex = 0; columnIndex < this.column; columnIndex++) {
|
|
|
- let gridData: GridDataInterface = {
|
|
|
- name: `Grid-${rowIndex}-${columnIndex}`,
|
|
|
- status: GridStatus.notUse,
|
|
|
- gridNode: null,
|
|
|
- row: rowIndex,
|
|
|
- column: columnIndex,
|
|
|
- gridColorKey: "null",
|
|
|
- gridType: 0
|
|
|
- }
|
|
|
- this.gridList[rowIndex].push(gridData)
|
|
|
- // 节点
|
|
|
- gridData.gridNode = new Node()
|
|
|
- this.gridsNode.addChild(gridData.gridNode)
|
|
|
- gridData.gridNode.name = `Grid-${rowIndex}-${columnIndex}`
|
|
|
- gridData.gridNode.addComponent(UITransform).setContentSize(this.gridSize, this.gridSize)
|
|
|
- const gridWidget: Widget = gridData.gridNode.addComponent(Widget)
|
|
|
- gridWidget.isAlignLeft = true
|
|
|
- gridWidget.left = this.gridSize * columnIndex + this.gridMargin
|
|
|
- gridWidget.isAlignBottom = true
|
|
|
- gridWidget.bottom = this.gridSize * rowIndex + this.gridMargin
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- generateGrid(gridData: GridDataInterface) {
|
|
|
- if (!gridData.gridNode) return;
|
|
|
- gridData.gridNode.children.forEach(node => { node.destroy() })
|
|
|
- let prefab = null
|
|
|
- if (gridData.status === GridStatus.notUse) {
|
|
|
- // prefab = this.gridPrefab
|
|
|
- prefab = this.gridPb;
|
|
|
- }
|
|
|
- else if (gridData.status === GridStatus.used) {
|
|
|
-
|
|
|
- //什么颜色的格子 --可以通过下标获取
|
|
|
- // prefab = this.prefabUrlMap[this.gameConfig['gridColor'][gridData.gridColorKey]['prefabUrl']]
|
|
|
- prefab = this.allBrickList[gridData.gridType];
|
|
|
-
|
|
|
- }
|
|
|
- const node = instantiate(prefab);
|
|
|
- if (!node) return;
|
|
|
- if (gridData.status === GridStatus.notUse) {
|
|
|
- node.getComponent(Sprite).color = this.notUseColor
|
|
|
- }
|
|
|
- gridData.gridNode.addChild(node)
|
|
|
- node.getComponent(UITransform).setContentSize(
|
|
|
- this.gridSize - this.gridMargin * 2,
|
|
|
- this.gridSize - this.gridMargin * 2,
|
|
|
- )
|
|
|
- node.setPosition(Vec3.ZERO)
|
|
|
- }
|
|
|
-
|
|
|
- generateBrick(brickKey: string, gridColorKey: string, gridType: number) {
|
|
|
- const brickConfig = this.brickListConfig['bricks'][brickKey]
|
|
|
- let rowMin = 0
|
|
|
- let rowMax = 0
|
|
|
- let columnMin = 0
|
|
|
- let columnMax = 0
|
|
|
- brickConfig['gridConfig'].forEach((gridConfigData: GridConfigDataInterface) => {
|
|
|
- if (gridConfigData.row < rowMin) {
|
|
|
- rowMin = gridConfigData.row
|
|
|
- }
|
|
|
- else if (gridConfigData.row > rowMax) {
|
|
|
- rowMax = gridConfigData.row
|
|
|
- }
|
|
|
- if (gridConfigData.column < columnMin) {
|
|
|
- columnMin = gridConfigData.column
|
|
|
- }
|
|
|
- else if (gridConfigData.column > columnMax) {
|
|
|
- columnMax = gridConfigData.column
|
|
|
- }
|
|
|
- })
|
|
|
- const rowNum = (rowMax - rowMin + 1)
|
|
|
- const columnNum = (columnMax - columnMin + 1)
|
|
|
- // 生成独立的方块节点
|
|
|
- const brickNode = new Node()
|
|
|
- brickNode.name = brickKey
|
|
|
- const transformCom: UITransform = brickNode.addComponent(UITransform)
|
|
|
- transformCom.setContentSize(
|
|
|
- this.gridSize * columnNum,
|
|
|
- this.gridSize * rowNum
|
|
|
- )
|
|
|
- transformCom.setAnchorPoint(0.5, 0.5)
|
|
|
- // const gridPrefab = this.prefabUrlMap[this.gameConfig['gridColor'][gridColorKey]['prefabUrl']]
|
|
|
- const gridPrefab = this.allBrickList[gridType];
|
|
|
- //通过配置初始化
|
|
|
- brickConfig['gridConfig'].forEach((gridConfigData: GridConfigDataInterface) => {
|
|
|
- const gridNode = new Node()
|
|
|
- gridNode.name = 'grid'
|
|
|
- brickNode.addChild(gridNode)
|
|
|
- gridNode.addComponent(UITransform).setContentSize(this.gridSize, this.gridSize)
|
|
|
- const gridWidget: Widget = gridNode.addComponent(Widget)
|
|
|
- gridWidget.isAlignLeft = true
|
|
|
- gridWidget.left = this.gridSize * gridConfigData.column - this.gridSize * columnMin
|
|
|
- gridWidget.isAlignBottom = true
|
|
|
- gridWidget.bottom = this.gridSize * gridConfigData.row - this.gridSize * rowMin
|
|
|
- const node = instantiate(gridPrefab)
|
|
|
- gridNode.addChild(node)
|
|
|
- node.getComponent(UITransform).setContentSize(
|
|
|
- this.gridSize - this.gridMargin * 2,
|
|
|
- this.gridSize - this.gridMargin * 2,
|
|
|
- )
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- node.setPosition(Vec3.ZERO)
|
|
|
- node.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
|
- event.preventSwallow = true;
|
|
|
- }, this);
|
|
|
- node.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
|
|
|
- event.preventSwallow = true;
|
|
|
- }, this);
|
|
|
- node.on(Node.EventType.TOUCH_END, (event: EventTouch) => {
|
|
|
- event.preventSwallow = true;
|
|
|
- }, this);
|
|
|
- })
|
|
|
-
|
|
|
- return brickNode
|
|
|
- }
|
|
|
- addBrick(index: number) {
|
|
|
- const bricks = this.brickListConfig.bricks || {};
|
|
|
- // const gridColors = this.gameConfig.gridColor || {};
|
|
|
- //获取方块的类型
|
|
|
- const brickKey = Object.keys(bricks)[randomRangeInt(0, Object.keys(bricks).length)];
|
|
|
- //获取方块的颜色随机下标
|
|
|
- // const gridColorKey = Object.keys(gridColors)[randomRangeInt(0, Object.keys(gridColors).length)];
|
|
|
-
|
|
|
- const gridColorKey = "GridColor1";
|
|
|
- //通过Key获取具体配置
|
|
|
- const brickConfig = bricks[brickKey];
|
|
|
- const gridType = randomRangeInt(0, this.allBrickList.length);
|
|
|
- const brickData: BrickDataInterface = {
|
|
|
- index,
|
|
|
- brickKey,
|
|
|
- rotateFlag: brickConfig['rotateFlag'],
|
|
|
- gridConfig: brickConfig['gridConfig'],
|
|
|
- deg: 0,
|
|
|
- brickNode: null,
|
|
|
- gridColorKey,
|
|
|
- brickInitPos: null,
|
|
|
- rotateNode: null,
|
|
|
- gridType: 0
|
|
|
- }
|
|
|
- this.bricksList.push(brickData)
|
|
|
- // 生成方块
|
|
|
- const brickNode = this.generateBrick(brickKey, gridColorKey, gridType)
|
|
|
- this.bricksNode.addChild(brickNode)
|
|
|
- brickData.brickNode = brickNode
|
|
|
- // 方块间隔
|
|
|
- let offset = 220
|
|
|
- if (this.brickNum % 2 === 1) {
|
|
|
- const middleNum = Math.floor(this.brickNum / 2) + 1
|
|
|
- if (index < middleNum) {
|
|
|
- offset = - offset
|
|
|
- }
|
|
|
- else if (index === middleNum) {
|
|
|
- offset = 0
|
|
|
- }
|
|
|
- }
|
|
|
- if (brickData && brickData.brickNode) {
|
|
|
- brickData.brickNode.setPosition(offset, 0)
|
|
|
- brickData.brickNode.scale_x = 0.6;
|
|
|
- brickData.brickNode.scale_y = 0.6;
|
|
|
- brickData.brickInitPos = brickData.brickNode.getWorldPosition()
|
|
|
- }
|
|
|
- // 添加旋转图标
|
|
|
- if (brickData.rotateFlag) {
|
|
|
- // brickData.rotateNode = instantiate(this.rotatePrefab)
|
|
|
- brickData.rotateNode = instantiate(this.rotatePb);
|
|
|
- this.rotateContainer.addChild(brickData.rotateNode)
|
|
|
- brickData.rotateNode.setWorldPosition(brickNode.getWorldPosition())
|
|
|
- }
|
|
|
- // 方块添加事件
|
|
|
- this.brickAddEvent(brickData)
|
|
|
- }
|
|
|
-
|
|
|
- brickAddEvent(brickData: BrickDataInterface) {
|
|
|
- const brickNode = brickData.brickNode
|
|
|
- if (!brickNode) return
|
|
|
- // 触摸时
|
|
|
- brickNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
|
- if (this.adShowingFlag || !this.operateFlag) return
|
|
|
-
|
|
|
- this.editingData.brickData = brickData
|
|
|
- this.editingData.gridList.length = 0
|
|
|
- // 记录开始触摸的位置
|
|
|
- this.touchStartPos.set(event.getUILocation())
|
|
|
- // 添加到移动节点里进行移动
|
|
|
- const pos = brickNode.getWorldPosition()
|
|
|
- brickNode.setParent(this.movingNode)
|
|
|
- brickNode.setWorldPosition(pos)
|
|
|
-
|
|
|
- const index = this.bricksList.findIndex(data => data === brickData)
|
|
|
- if (index > -1) {
|
|
|
- this.editingData.brickData = this.bricksList.splice(index, 1)[0]
|
|
|
- } else {
|
|
|
- console.error("bricksList not find brickData:", brickData)
|
|
|
- }
|
|
|
- })
|
|
|
- // 触摸移动时
|
|
|
- brickNode.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
|
|
|
- if (this.adShowingFlag || !this.operateFlag) return
|
|
|
-
|
|
|
- const movePos: Vec2 = event.getUILocation().subtract(this.touchStartPos)
|
|
|
- // 挪动很小时,不移动方块组合
|
|
|
- if (movePos.length() <= this.rotateFaultTolerant) {
|
|
|
- return
|
|
|
- }
|
|
|
- // 隐藏旋转节点
|
|
|
- if (this.editingData.brickData?.rotateFlag && this.editingData.brickData.rotateNode) {
|
|
|
- this.editingData.brickData.rotateNode.active = false
|
|
|
- }
|
|
|
- // 格子颜色恢复
|
|
|
- this.gridColorRecovery()
|
|
|
- // 移动
|
|
|
- brickNode.setWorldPosition(event.getUILocation().toVec3().add3f(0, this.yOffset, 0))
|
|
|
- // 每次移动重置数据
|
|
|
- this.editingData.gridList.length = 0
|
|
|
- // 实时获取方块位置判断在哪个格子上
|
|
|
- const tempGridList: GridDataInterface[] = []
|
|
|
- brickNode.children.forEach((brickGridNode) => {
|
|
|
- const brickGridPos = brickGridNode.getWorldPosition()
|
|
|
- let gridData: GridDataInterface | null = null
|
|
|
- for (let rowIndex = 0; rowIndex < this.row && gridData === null; rowIndex++) {
|
|
|
- for (let columnIndex = 0; columnIndex < this.column && gridData === null; columnIndex++) {
|
|
|
- const nowGridData = this.gridList[rowIndex][columnIndex]
|
|
|
- if (!nowGridData?.gridNode) continue
|
|
|
- const gridPos = nowGridData.gridNode.getWorldPosition()
|
|
|
- if (Vec3.distance(gridPos, brickGridPos) <= (this.gridSize / 2 - this.gridMargin)) {
|
|
|
- gridData = nowGridData
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (gridData === null) return
|
|
|
- tempGridList.push(gridData)
|
|
|
- })
|
|
|
- // 检查整体情况
|
|
|
- let checkFlag = false
|
|
|
- if (
|
|
|
- tempGridList.length === brickData.gridConfig.length &&
|
|
|
- tempGridList.filter(d => d.status === GridStatus.notUse).length === brickData.gridConfig.length
|
|
|
- ) {
|
|
|
- checkFlag = true
|
|
|
- tempGridList.forEach((gridData) => {
|
|
|
- this.editingData.gridList.push(gridData)
|
|
|
- })
|
|
|
- }
|
|
|
- // 格子给用户提示
|
|
|
- tempGridList.forEach((gridData) => {
|
|
|
- if (gridData.status !== GridStatus.notUse || !gridData.gridNode) return
|
|
|
- const sprite = gridData.gridNode.children[0]?.getComponent(Sprite)
|
|
|
- if (sprite) {
|
|
|
- sprite.color = checkFlag ? this.usableColor : this.unavailableColor
|
|
|
- // 用于恢复格子
|
|
|
- this.gridColorList.push(gridData)
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
- // 触摸松开后
|
|
|
- brickNode.on(Node.EventType.TOUCH_END, this.brickTouchEnd, this)
|
|
|
- brickNode.on(Node.EventType.TOUCH_CANCEL, this.brickTouchEnd, this)
|
|
|
- }
|
|
|
-
|
|
|
- brickTouchEnd(event: EventTouch) {
|
|
|
- if (this.adShowingFlag || !this.operateFlag) return
|
|
|
- this.operateFlag = false
|
|
|
- // 单击旋转
|
|
|
- if (
|
|
|
- this.editingData.brickData.rotateFlag &&
|
|
|
- event.getUILocation().subtract(this.touchStartPos).length() <= this.rotateFaultTolerant
|
|
|
- ) {
|
|
|
- const brickData = this.editingData.brickData
|
|
|
- // 方块放回待选区
|
|
|
- if (brickData.brickNode && brickData.brickInitPos) {
|
|
|
- this.bricksList.push(brickData)
|
|
|
- this.bricksNode.addChild(brickData.brickNode)
|
|
|
- brickData.brickNode.setWorldPosition(brickData.brickInitPos)
|
|
|
- // 旋转
|
|
|
- this.brickGridRotate(brickData).then(() => {
|
|
|
- this.operateFlag = true
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- // 方块到格子
|
|
|
- else if (this.editingData.brickData && this.editingData.gridList.length > 0) {
|
|
|
- // 修改格子
|
|
|
- this.editingData.gridList.forEach((gridData) => {
|
|
|
- gridData.status = GridStatus.used
|
|
|
- gridData.gridColorKey = this.editingData.brickData.gridColorKey
|
|
|
- this.generateGrid(gridData)
|
|
|
- })
|
|
|
- // 销毁方块
|
|
|
- if (this.editingData.brickData.brickNode) {
|
|
|
- this.editingData.brickData.brickNode.destroy()
|
|
|
- }
|
|
|
- // 销毁旋转节点
|
|
|
- if (this.editingData.brickData.rotateFlag && this.editingData.brickData.rotateNode) {
|
|
|
- this.editingData.brickData.rotateNode.destroy()
|
|
|
- }
|
|
|
- // 新增方块
|
|
|
- this.addBrick(this.editingData.brickData.index)
|
|
|
- this.scheduleOnce(() => {
|
|
|
- // 格子消除
|
|
|
- this.gridEliminate().then(() => {
|
|
|
- // 检查方块是否还能消除格子
|
|
|
- this.prompt(false).then((promptFlag: boolean) => {
|
|
|
- if (!promptFlag) {
|
|
|
- this.gameOver()
|
|
|
- }
|
|
|
- this.operateFlag = true
|
|
|
- })
|
|
|
- })
|
|
|
- })
|
|
|
- }
|
|
|
- // 方块回到待选区
|
|
|
- else {
|
|
|
- const brickData = this.editingData.brickData
|
|
|
- this.bricksList.push(brickData)
|
|
|
- this.operateFlag = false
|
|
|
- // 回弹动画
|
|
|
- if (brickData.brickNode) {
|
|
|
- const pos = this.editingData.brickData.brickInitPos
|
|
|
- if (!pos) {
|
|
|
- return;
|
|
|
- }
|
|
|
- tween(brickData.brickNode)
|
|
|
- .to(this.aniBrickMove, { worldPosition: pos })
|
|
|
- .call(() => {
|
|
|
- if (brickData.brickNode && brickData.brickInitPos && brickData.rotateNode) {
|
|
|
- this.bricksNode.addChild(brickData.brickNode)
|
|
|
- brickData.brickNode.setWorldPosition(brickData.brickInitPos)
|
|
|
- if (brickData.rotateFlag) {
|
|
|
- brickData.rotateNode.active = true
|
|
|
- }
|
|
|
- this.operateFlag = true
|
|
|
- }
|
|
|
- })
|
|
|
- .start()
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- // 格子颜色恢复
|
|
|
- this.gridColorRecovery()
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //格子颜色恢复
|
|
|
- gridColorRecovery() {
|
|
|
- while (this.gridColorList.length > 0) {
|
|
|
- const gridData = this.gridColorList.pop()
|
|
|
- if (gridData?.gridNode && gridData.status === GridStatus.notUse) {
|
|
|
- const sprite = gridData.gridNode.children[0]?.getComponent(Sprite)
|
|
|
- if (sprite) {
|
|
|
- sprite.color = this.notUseColor
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- nextGridRotate(gridConfig: GridConfigDataInterface[], deg: number) {
|
|
|
- const newGridConfig: GridConfigDataInterface[] = []
|
|
|
- // 顺时针旋转
|
|
|
- let newDeg = deg - 90
|
|
|
- gridConfig.forEach((gridConfigData) => {
|
|
|
- // 例如(1,2) => (-2,1),可以画图分析
|
|
|
- newGridConfig.push({
|
|
|
- row: -gridConfigData.column,
|
|
|
- column: gridConfigData.row
|
|
|
- })
|
|
|
- })
|
|
|
- return { gridConfig: newGridConfig, deg: newDeg }
|
|
|
- }
|
|
|
-
|
|
|
- 'brickGridRotate'(brickData: BrickDataInterface) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- // this.audioManager.playRotate()
|
|
|
- const next = this.nextGridRotate(brickData.gridConfig, brickData.deg)
|
|
|
- brickData.deg = next.deg
|
|
|
- brickData.gridConfig = next.gridConfig
|
|
|
-
|
|
|
- if (brickData.brickNode) {
|
|
|
- tween(brickData.brickNode)
|
|
|
- .to(this.aniBrickRotate, { angle: next.deg })
|
|
|
- .call(() => {
|
|
|
- resolve(true)
|
|
|
- }).start()
|
|
|
- }
|
|
|
-
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- gridEliminateCheck(gridList: GridDataInterface[][]) {
|
|
|
- const gridEliminateList: GridDataInterface[] = []
|
|
|
- let eliminateRowNum = 0
|
|
|
- let eliminateColumnNum = 0
|
|
|
- // 行检查
|
|
|
- for (let rowIndex = 0; rowIndex < this.row; rowIndex++) {
|
|
|
- const rowData = gridList[rowIndex]
|
|
|
- if (rowData.every(gridData => gridData.status === GridStatus.used)) {
|
|
|
- rowData.forEach(gridData => {
|
|
|
- if (gridEliminateList.findIndex(data => data === gridData) < 0) {
|
|
|
- gridEliminateList.push(gridData)
|
|
|
- }
|
|
|
- })
|
|
|
- eliminateRowNum += 1
|
|
|
- }
|
|
|
- }
|
|
|
- // 列检查
|
|
|
- for (let columnIndex = 0; columnIndex < this.column; columnIndex++) {
|
|
|
- if (gridList.every(rowData => rowData[columnIndex].status === GridStatus.used)) {
|
|
|
- gridList.forEach(rowData => {
|
|
|
- const gridData = rowData[columnIndex]
|
|
|
- if (gridEliminateList.findIndex(data => data === gridData) < 0) {
|
|
|
- gridEliminateList.push(gridData)
|
|
|
- }
|
|
|
- })
|
|
|
- eliminateColumnNum += 1
|
|
|
- }
|
|
|
- }
|
|
|
- return {
|
|
|
- gridEliminateList,
|
|
|
- eliminateRowNum,
|
|
|
- eliminateColumnNum,
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 消除
|
|
|
- gridEliminate() {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- const d = this.gridEliminateCheck(this.gridList)
|
|
|
- const gridEliminateList = d.gridEliminateList
|
|
|
- const eliminateRowNum = d.eliminateRowNum
|
|
|
- const eliminateColumnNum = d.eliminateColumnNum
|
|
|
- // 无行可消除
|
|
|
- if (gridEliminateList.length < 1) {
|
|
|
- resolve(false)
|
|
|
- return
|
|
|
- }
|
|
|
- // 消除格子
|
|
|
- gridEliminateList.forEach((gridData) => {
|
|
|
- if (gridData.gridNode) {
|
|
|
- tween(gridData.gridNode.children[0])
|
|
|
- .to(this.aniBrickEliminate, { scale: new Vec3(0.5, 0.5) })
|
|
|
- .call(() => {
|
|
|
- gridData.status = GridStatus.notUse
|
|
|
- this.generateGrid(gridData)
|
|
|
- })
|
|
|
- .start()
|
|
|
- }
|
|
|
- })
|
|
|
- // 音效
|
|
|
- // this.audioManager.playEliminate()
|
|
|
- this.scheduleOnce(() => {
|
|
|
- // 成绩
|
|
|
- let score = 0
|
|
|
- for (let i = 1; i <= eliminateRowNum; i++) {
|
|
|
- score += this.column * i
|
|
|
- }
|
|
|
- for (let i = 1; i <= eliminateColumnNum; i++) {
|
|
|
- score += this.row * i
|
|
|
- }
|
|
|
- this.score += score
|
|
|
- resolve(true)
|
|
|
- }, 0.2)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- gameOver() {
|
|
|
- // this.audioManager.playGameOver()
|
|
|
- this.setGameStauts(GameStatus.end)
|
|
|
- }
|
|
|
-
|
|
|
- moveIf(row: number, column: number, gridConfig: GridConfigDataInterface[]) {
|
|
|
- let moveFlag = true
|
|
|
- for (let i = 0; i < gridConfig.length; i++) {
|
|
|
- const gridConfigData = gridConfig[i]
|
|
|
- const gridI = row + gridConfigData.row
|
|
|
- const gridJ = column + gridConfigData.column
|
|
|
- // 边界判断
|
|
|
- if (
|
|
|
- gridI < 0 ||
|
|
|
- gridI > this.row - 1 ||
|
|
|
- gridJ < 0 ||
|
|
|
- gridJ > this.column - 1
|
|
|
- ) {
|
|
|
- moveFlag = false
|
|
|
- break
|
|
|
- }
|
|
|
- // 已用
|
|
|
- else if (this.gridList[gridI][gridJ].status === GridStatus.used) {
|
|
|
- moveFlag = false
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- return moveFlag
|
|
|
- }
|
|
|
-
|
|
|
- copyGridList() {
|
|
|
- const gridList: GridDataInterface[][] = []
|
|
|
- for (let rowIndex = 0; rowIndex < this.row; rowIndex++) {
|
|
|
- gridList.push([])
|
|
|
- for (let columnIndex = 0; columnIndex < this.column; columnIndex++) {
|
|
|
- const gridData = this.gridList[rowIndex][columnIndex]
|
|
|
- gridList[rowIndex].push({
|
|
|
- name: gridData.name,
|
|
|
- status: gridData.status,
|
|
|
- gridNode: null,
|
|
|
- row: gridData.row,
|
|
|
- column: gridData.column,
|
|
|
- gridColorKey: gridData.gridColorKey,
|
|
|
- gridType: gridData.gridType
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- return gridList
|
|
|
- }
|
|
|
-
|
|
|
- prompt(tipFlag = true) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- const gridPromptList: GridDataInterface[] = []
|
|
|
- let moveFlag = false
|
|
|
- // 找方块可消除位置
|
|
|
- for (let rowIndex = 0; rowIndex < this.row && !moveFlag; rowIndex++) {
|
|
|
- for (let columnIndex = 0; columnIndex < this.column && !moveFlag; columnIndex++) {
|
|
|
- const gridData = this.gridList[rowIndex][columnIndex]
|
|
|
- if (gridData.status !== GridStatus.notUse) continue
|
|
|
- // 方块不旋转检测是否能放
|
|
|
- for (let brickI = 0; brickI < this.bricksList.length && !moveFlag; brickI++) {
|
|
|
- const brickData = this.bricksList[brickI]
|
|
|
- if (this.moveIf(rowIndex, columnIndex, brickData.gridConfig)) {
|
|
|
- // 复制整体网格,以方块设置网格状态
|
|
|
- const gridList = this.copyGridList()
|
|
|
- brickData.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex].status = GridStatus.used
|
|
|
- })
|
|
|
- // 检查复制的整体网格是否有可消除
|
|
|
- if (this.gridEliminateCheck(gridList).gridEliminateList.length > 0) {
|
|
|
- moveFlag = true
|
|
|
- brickData.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridPromptList.push(this.gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex])
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 方块旋转检测是否能放
|
|
|
- for (let brickI = 0; brickI < this.bricksList.length && !moveFlag; brickI++) {
|
|
|
- const brickData = this.bricksList[brickI]
|
|
|
- if (!brickData.rotateFlag) continue
|
|
|
- let gridConfig = brickData.gridConfig
|
|
|
- let deg = brickData.deg
|
|
|
- // 获得旋转的方块网格配置
|
|
|
- for (let count = 1; count <= 3 && !moveFlag; count++) {
|
|
|
- const next = this.nextGridRotate(gridConfig, deg)
|
|
|
- if (this.moveIf(rowIndex, columnIndex, next.gridConfig)) {
|
|
|
- // 复制整体网格,以方块设置网格状态
|
|
|
- const gridList = this.copyGridList()
|
|
|
- next.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex].status = GridStatus.used
|
|
|
- })
|
|
|
- // 检查复制的整体网格是否有可消除
|
|
|
- if (this.gridEliminateCheck(gridList).gridEliminateList.length > 0) {
|
|
|
- moveFlag = true
|
|
|
- next.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridPromptList.push(this.gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex])
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- gridConfig = next.gridConfig
|
|
|
- deg = next.deg
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 找方块可放置位置
|
|
|
- for (let rowIndex = 0; rowIndex < this.row && !moveFlag; rowIndex++) {
|
|
|
- for (let columnIndex = 0; columnIndex < this.column && !moveFlag; columnIndex++) {
|
|
|
- const gridData = this.gridList[rowIndex][columnIndex]
|
|
|
- if (gridData.status !== GridStatus.notUse) continue
|
|
|
- // 方块不旋转检测是否能放
|
|
|
- for (let brickI = 0; brickI < this.bricksList.length && !moveFlag; brickI++) {
|
|
|
- const brickData = this.bricksList[brickI]
|
|
|
- if (this.moveIf(rowIndex, columnIndex, brickData.gridConfig)) {
|
|
|
- moveFlag = true
|
|
|
- brickData.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridPromptList.push(this.gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex])
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- // 方块旋转检测是否能放
|
|
|
- for (let brickI = 0; brickI < this.bricksList.length && !moveFlag; brickI++) {
|
|
|
- const brickData = this.bricksList[brickI]
|
|
|
- if (!brickData.rotateFlag) continue
|
|
|
- let gridConfig = brickData.gridConfig
|
|
|
- let deg = brickData.deg
|
|
|
- for (let count = 1; count <= 3 && !moveFlag; count++) {
|
|
|
- const next = this.nextGridRotate(gridConfig, deg)
|
|
|
- if (this.moveIf(rowIndex, columnIndex, next.gridConfig)) {
|
|
|
- moveFlag = true
|
|
|
- next.gridConfig.forEach((gridConfigData) => {
|
|
|
- gridPromptList.push(this.gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex])
|
|
|
- })
|
|
|
- }
|
|
|
- gridConfig = next.gridConfig
|
|
|
- deg = next.deg
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (gridPromptList.length < 1) {
|
|
|
- resolve(false)
|
|
|
- return
|
|
|
- }
|
|
|
- if (!tipFlag) {
|
|
|
- resolve(true)
|
|
|
- return
|
|
|
- }
|
|
|
- // 提示用户(网格变绿)
|
|
|
- gridPromptList.forEach((gridData) => {
|
|
|
- if (gridData.gridNode) {
|
|
|
- const sprite = gridData.gridNode.children[0]?.getComponent(Sprite)
|
|
|
- if (sprite) {
|
|
|
- sprite.color = this.usableColor
|
|
|
- // 用于恢复格子
|
|
|
- this.gridColorList.push(gridData)
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- resolve(true)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //重新开始
|
|
|
- onRefreshBtnClick() {
|
|
|
- if (
|
|
|
- this.gameStatus !== GameStatus.running ||
|
|
|
- !this.operateFlag ||
|
|
|
- this.adShowingFlag
|
|
|
- ) return
|
|
|
-
|
|
|
- this.setAdShowingFlag(true)
|
|
|
- this.bricksNode.destroyAllChildren()
|
|
|
- this.rotateContainer.destroyAllChildren()
|
|
|
- this.bricksList.length = 0
|
|
|
- for (let i = 1; i <= this.brickNum; i++) {
|
|
|
- this.addBrick(i)
|
|
|
- }
|
|
|
- // 恢复格子颜色
|
|
|
- this.gridColorRecovery()
|
|
|
- this.setAdShowingFlag(false)
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- //--复活
|
|
|
- onPromptBtnClick() {
|
|
|
- if (
|
|
|
- this.gameStatus !== GameStatus.running ||
|
|
|
- !this.operateFlag ||
|
|
|
- this.adShowingFlag
|
|
|
- ) return
|
|
|
-
|
|
|
- // 先检查是否死局
|
|
|
- this.prompt(false).then((flag) => {
|
|
|
- if (!flag) {
|
|
|
- this.gameOver()
|
|
|
- return
|
|
|
- }
|
|
|
- // 非死局,打开广告
|
|
|
- this.setAdShowingFlag(true)
|
|
|
- // SDKManager.showVideoAd().then((isEnded: boolean) => {
|
|
|
- // if (isEnded) {
|
|
|
- // this.gridColorRecovery()
|
|
|
- // this.prompt()
|
|
|
- // }
|
|
|
- // this.setAdShowingFlag(false)
|
|
|
- // }).catch((err) => {
|
|
|
- // console.error('onPromptBtnClick', err)
|
|
|
- // this.setAdShowingFlag(false)
|
|
|
- // })
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- //再来一次
|
|
|
- onAgainBtnClick() {
|
|
|
- if (!this.operateFlag) return
|
|
|
-
|
|
|
- this.initData()
|
|
|
- }
|
|
|
-
|
|
|
- //确认游戏
|
|
|
- onContinueBtnClick() {
|
|
|
- this.setGameStauts(GameStatus.running)
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|