CocosCreator项目实战(07):移动与合并

文章目录

  • 一、算法思路
  • 二、算法框架
  • 三、代码补完


一、算法思路

  1. 递归实现思路:
    每一步迭代分为以下几种情况进行处理:
    a. 移动到顶:结束迭代;
    b. 当前数字为空:结束迭代;
    c. 移动方向上前一个数字格为空:向该方向移动;
    d. 移动方向上前一个数字格相同:合并,结束迭代;
    e. 移动方向上前一个数字格不同:结束迭代。

二、算法框架

  1. 按照以上思路先写好算法框架。
    move()方法即移动函数,toMove数组即要移动的数字块,通过循环遍历将非空的数字块存储在toMove数组中,counter用于统计完成移动的数字块的个数,接下来调用toMove.lengthmove()方法,每次移动完需要调用afterMove()方法用于生成新的数字块。
    moveLeft() {
        console.log('move left');
            
        let move = (x, y, callback) => {

        };

        let toMove = [];
        for (let i = 0; i < ROWS; ++i) {
            for (let j = 0; j < ROWS; ++j) {
                if (this.data[i][j] != 0) {
                    toMove.push({ x: i, y: j });
                }
            }
        }
        let counter = 0;
        for (let i = 0; i < toMove.length; ++i) {
            move(toMove[i].x, toMove[i].y, () => {
                counter++;
                if (counter == toMove.length) {
                    this.afterMove();
                }
            });
        }
    },

    afterMove() {

    },

三、代码补完

  1. 首先编写doMove()函数表示block实体的移动动画,使用cc.tween()方法先在指定时间内移动到的位置,然后调用回调函数。
    doMove(block, position, callback) {
        cc.tween(block)
            .to(MOVE_DURATION, { position })
            .call(() => {
                callback && callback()
            })
            .start();
    },
  1. moveLeft()方法中,先定义一个标签hasMoved标识往左滑动这个操作是否有导致数字块的变化,然后对这个move方法按照之前的算法思路分五种情况进行讨论:
    a. 移动到顶 & b. 当前数字为空:结束迭代;
    c. 移动方向上前一个数字格为空:向该方向移动。将当前blockdata与移动方向上前一格绑定,当前格清零,并调用doMove()函数完成实体移动动画,最后hasMoved标签置为true表示有数字块的变化;
    d. 移动方向上前一个数字格相同:合并。将data * 2与移动方向上前一格绑定,当前格清零,当前格block置为null,前一个生成新的拥有data * 2值的数字块,并调用doMove()函数完成实体移动动画,最后hasMoved标签置为true表示有数字块的变化;
    e. 移动方向上前一个数字格不同:结束迭代。
    moveLeft() {
        console.log('move left');
        let hasMoved = false;
        let move = (x, y, callback) => {
            if (y == 0 || this.data[x][y] == 0) {
                callback && callback();
                return;
            } else if (this.data[x][y - 1] == 0) {
                // Move
                let block = this.blocks[x][y];
                let position = this.positions[x][y - 1];
                this.blocks[x][y - 1] = block;
                this.data[x][y - 1] = this.data[x][y];
                this.data[x][y] = 0;
                this.blocks[x][y] = null;
                this.doMove(block, position, () => {
                    move(x, y - 1, callback);
                });
                hasMoved = true;
            } else if (this.data[x][y - 1] == this.data[x][y]) {
                // Merge
                let block = this.blocks[x][y];
                let position = this.positions[x][y - 1];
                this.data[x][y - 1] *= 2;
                this.data[x][y] = 0;
                this.blocks[x][y] = null;
                this.blocks[x][y - 1].getComponent('block').setNumber(this.data[x][y - 1]);
                this.doMove(block, position, () => {
                    block.destroy();
                    callback && callback();
                });
                hasMoved = true;
            } else {
                callback && callback();
                return;
            }
        };
        ...
        let counter = 0;
        for (let i = 0; i < toMove.length; ++i) {
            move(toMove[i].x, toMove[i].y, () => {
                counter++;
                if (counter == toMove.length) {
                    this.afterMove(hasMoved);
                }
            });
        }
    },
  1. 定义afterMove(hasMoved)方法,根据hasMoved为true有移动操作,调用addBlock()随机生成新的数字快。
    afterMove(hasMoved) {
        if (hasMoved) {
            this.addBlock();
        }
    },
  1. 预览可得。

CocosCreator项目实战(07):移动与合并_第1张图片

  1. 按照相同思路可将四个move()方法整合为一个moveDirection(direction)方法。首先修改touchEnd(event)函数,在四个方向上均调用moveDirection()函数但传入不同的参数。而后修改moveLeft()方法moveDirection(direction)方法
    touchEnd(event) {
		...
        if (vec.mag() > MIN_LENGTH) {
            if (Math.abs(vec.x) > Math.abs(vec.y)) {
                // Horizontal
                if (vec.x < 0) {
                    this.moveDirection('left');
                } else {
                    this.moveDirection('right');
                }
            } else {
                // Vertical
                if (vec.y > 0) {
                    this.moveDirection('up');
                } else {
                    this.moveDirection('down');
                }
            }
        }
    },
    ...
    moveDirection(direction) {
        console.log('move ' + direction);
        let tags = [{ x: 0, y: -1 }, { x: 0, y: 1 }, { x: 1, y: 0 }, { x: -1, y: 0 }];
        let hasMoved = false;
        let move = (x, y, callback) => {
            let condition, tag;
            switch (direction) {
                case 'left':
                    tag = tags[0];
                    condition = (y == 0);
                    break;
                case 'right':
                    tag = tags[1];
                    condition = (y == ROWS - 1);
                    break;
                case 'up':
                    tag = tags[2];
                    condition = (x == ROWS - 1);
                    break;
                case 'down':
                    tag = tags[3];
                    condition = (x == 0);
                    break;
            }
            let destX = x + tag.x;
            let destY = y + tag.y;
            if (condition || this.data[x][y] == 0) {
                callback && callback();
                return;
            } else if (this.data[destX][destY] == 0) {
                // Move
                let block = this.blocks[x][y];
                let position = this.positions[destX][destY];
                this.blocks[destX][destY] = block;
                this.data[destX][destY] = this.data[x][y];
                this.data[x][y] = 0;
                this.blocks[x][y] = null;
                this.doMove(block, position, () => {
                    move(destX, destY, callback);
                });
                hasMoved = true;
            } else if (this.data[destX][destY] == this.data[x][y]) {
                // Merge
                let block = this.blocks[x][y];
                let position = this.positions[destX][destY];
                this.data[destX][destY] *= 2;
                this.data[x][y] = 0;
                this.blocks[x][y] = null;
                this.blocks[destX][destY].getComponent('block').setNumber(this.data[destX][destY]);
                this.doMove(block, position, () => {
                    block.destroy();
                    callback && callback();
                });
                hasMoved = true;
            } else {
                callback && callback();
                return;
            }
        };

        let toMove = [];
        switch (direction) {
            case 'left':
                for (let i = 0; i < ROWS; ++i) {
                    for (let j = 0; j < ROWS; ++j) {
                        if (this.data[i][j] != 0) {
                            toMove.push({ x: i, y: j });
                        }
                    }
                }
                break;
            case 'right':
                for (let i = 0; i < ROWS; ++i) {
                    for (let j = ROWS - 1; j >= 0; --j) {
                        if (this.data[i][j] != 0) {
                            toMove.push({ x: i, y: j });
                        }
                    }
                }
                break;
            case 'up':
                for (let i = ROWS - 1; i >= 0; --i) {
                    for (let j = 0; j < ROWS; ++j) {
                        if (this.data[i][j] != 0) {
                            toMove.push({ x: i, y: j });
                        }
                    }
                }
                break;
            case 'down':
                for (let i = 0; i < ROWS; ++i) {
                    for (let j = 0; j < ROWS; ++j) {
                        if (this.data[i][j] != 0) {
                            toMove.push({ x: i, y: j });
                        }
                    }
                }
                break;
        }

        let counter = 0;
        for (let i = 0; i < toMove.length; ++i) {
            move(toMove[i].x, toMove[i].y, () => {
                counter++;
                if (counter == toMove.length) {
                    this.afterMove(hasMoved);
                }
            });
        }
    },
  1. 预览可得。

CocosCreator项目实战(07):移动与合并_第2张图片


你可能感兴趣的:(CocosCreator)