cocos creator实例--CocosCreator实现的1024游戏

效果预览

游戏介绍

● Github上的代码,不能进行合并操作,修改以后,功能类似2048,空白块赏随机位置,生成2,可以往左、右、上、下滑动,数字会朝着指定方向运动,相邻元素如果相同,则合并。

游戏代码参考:https://github.com/potato47/1024

  工程结构介绍

● 游戏分3个场景,game、sleep、success,sleep是不玩显示的,success是成功显示的,game是游戏核心场景,玩游戏都在此场景进行。

  • 游戏中的数字块都在TileLayer节点上,游戏核心逻辑Map挂在到Map节点上。

  • 每个数字块,通过对预制初始化,放置在界面上,预制Tile负责数字块的显示,挂在有Tile脚本组件。

  算法介绍

● 游戏的核心算法在Map脚本上,通过滑动结束点和起始点,判断滑动的方向,可以向左、右、上、下滑动,滑动后执行相应的逻辑onLeftSlide、onRightSlide、onUpSlide、onDownSlide,根据方向进行合并操作,相邻的元素,如果是相同的则合并,如果是空的,则向滑动方向移动。

● 核心的算法mergeArray,对传入的数组往右移动,然后相同的合并。

● 如四格的数字分别是[2,0,0,2],往右滑动以后,就会变成[0,0,2,2],最右边的相同,就执行合并操作,最终变成[0,0,0,4]。

● 又如[2,0,2,2],第一步移动后变成[0,2,2,2],从最后侧开始合并,合并第一步变成[0,2,0,4],再移动变成[0,0,2,4]。

● 类似上述操作,无论是向上、下、左、右滑动,只需要改变传入的数组元素的顺序即可。

//---------------Map.js------------------------

cc.Class({
    extends: cc.Component,

    properties: {
        tilePrefab: cc.Prefab,
        tileLayer: cc.Node,
    },

    // use this for initialization
    onLoad: function () {
        cc.map = this;
        this.mapWidth = this.node.width;
        this.tileWidth = this.mapWidth / 4;
        this.g = this.getComponent(cc.Graphics);
        this.touchStartPosition = cc.v2();
        this.touchEndPosition = cc.v2();
        this.node.on(cc.Node.EventType.TOUCH_START, (event) => {
            this.touchStartPosition = event.getLocation();
        });
        this.node.on(cc.Node.EventType.TOUCH_END, (event) => {
            this.touchEndPosition = event.getLocation();
            let offsetX = this.touchEndPosition.x - this.touchStartPosition.x;
            let offsetY = this.touchEndPosition.y - this.touchStartPosition.y;
            if (Math.abs(offsetX) > Math.abs(offsetY)) {
                if (offsetX > 15) {
                    this.onRightSlide();
                    cc.log('right');
                } else if (offsetX < -15) {
                    this.onLeftSlide();
                    cc.log('left');
                }
            } else {
                if (offsetY > 15) {
                    this.onUpSlide();
                    cc.log('up');
                } else if (offsetY < -15) {
                    this.onDownSlide();
                    cc.log('down');
                }
            }
        });
        this.drawBg();
        this.initTiles();

        this.mergeArray([0,0,2,8]);
    },

    /**
     * @description: 合并arr
     * @param {array} arr
     * @return: 
     */
    mergeArray(arr){
        if(arr.length <= 0){
            return;
        }

        cc.log('#1', arr);

        // 按照顺序取出非0值
        let src = [];
        for(let i = 0; i < arr.length; i++){
            if(arr[i] != 0){
                src.push(arr[i]);
            }
        }        

        // 模拟栈
        let stack = [];
        while(src.length > 0){
            // 栈是空或栈顶元素和源数据最后一个不一样
            if(stack.length <= 0 || stack[0] != src[src.length - 1]){
                stack.unshift(src[src.length-1]);
                src.splice(src.length -1, 1);
            }
            // 栈顶出栈
            else{
                src[src.length-1] = src[src.length-1] * 2;
                stack.splice(0, 1);
            }
        }
        cc.log('#2', stack);

        return stack;
    },

    onLeftSlide() {
        // 判断是否有tile移动
        let isMove = false; 

        for (let y = 0; y < 4; y++) {
            let src = [];
            for(let x = 3; x >= 0; x--){
                src.push(this.tiles[x][y].number);
            }
            let stack = this.mergeArray(src);

            // 有变化
            if(stack.length != src.length){
                for(let x = 0; x < 4; x++){
                    if(stack.length > 0){
                        this.tiles[x][y].number = stack[stack.length - 1];
                        stack.splice(stack.length-1, 1);
                    }
                    else{
                        this.tiles[x][y].number = 0;
                    }
                }
                isMove = true;
            }
        }

        // 没变化
        if(!isMove){
            return;
        }
        
        if (isMove) {
            this.newTile();
            this.judgeOver();
        }
    },

    onRightSlide() {
        // 判断是否有tile移动
        let isMove = false; 

        for (let y = 0; y < 4; y++) {
            let src = [];
            for(let x = 0; x < 4; x++){
                src.push(this.tiles[x][y].number);
            }
            let stack = this.mergeArray(src);

            // 有变化
            if(stack.length != src.length){
                for(let x = 3; x >= 0; x--){
                    if(stack.length > 0){
                        this.tiles[x][y].number = stack[stack.length - 1];
                        stack.splice(stack.length-1, 1);
                    }
                    else{
                        this.tiles[x][y].number = 0;
                    }
                }
                isMove = true;
            }
        }

        // 没变化
        if(!isMove){
            return;
        }

        //有tile移动才添加新的tile
        if (isMove) {
            this.newTile();
            this.judgeOver();
        }
    },

    onDownSlide() {
        // 判断是否有tile移动
        let isMove = false; 

        for (let x = 0; x < 4; x++) {
            let src = [];
            for(let y = 3; y >= 0; y--){
                src.push(this.tiles[x][y].number);
            }
            let stack = this.mergeArray(src);

            // 有变化
            if(stack.length != src.length){
                for(let y = 0; y < 4; y++){
                    if(stack.length > 0){
                        this.tiles[x][y].number = stack[stack.length - 1];
                        stack.splice(stack.length-1, 1);
                    }
                    else{
                        this.tiles[x][y].number = 0;
                    }
                }
                isMove = true;
            }
        }

        // 没变化
        if(!isMove){
            return;
        }
        
        if (isMove) {
            this.newTile();
            this.judgeOver();
        }
    },

    onUpSlide() {
        // 判断是否有tile移动
        let isMove = false; 

        for (let x = 0; x < 4; x++) {
            let src = [];
            for(let y = 0; y < 4; y++){
                src.push(this.tiles[x][y].number);
            }
            let stack = this.mergeArray(src);

            // 有变化
            if(stack.length != src.length){
                for(let y = 3; y >= 0; y--){
                    if(stack.length > 0){
                        this.tiles[x][y].number = stack[stack.length - 1];
                        stack.splice(stack.length-1, 1);
                    }
                    else{
                        this.tiles[x][y].number = 0;
                    }
                }
                isMove = true;
            }
        }

        // 没变化
        if(!isMove){
            return;
        }
        
        if (isMove) {
            this.newTile();
            this.judgeOver();
        }
    },

    drawBg() {
        this.g.rect(0, 0, this.node.width, this.node.height);
        this.g.fillColor = new cc.Color().fromHEX('#0000ff');//cc.hexToColor('#ffffff');
        this.g.stroke();
        this.g.fill();
        this.g.strokeColor = cc.Color.BLACK;
        this.g.lineWidth = 10;
        for (let x = 0; x < 5; x++) {
            this.g.moveTo(x * this.tileWidth, 0);
            this.g.lineTo(x * this.tileWidth, this.mapWidth);
        }
        for (let y = 0; y < 5; y++) {
            this.g.moveTo(0, y * this.tileWidth);
            this.g.lineTo(this.mapWidth, y * this.tileWidth);
        }
        this.g.stroke();
    },

    judgeOver() {
        for(let x = 0; x < 4;x++){
            for(let y = 0; y < 4; y++) {
                if(this.tiles[x][y].number === 1024) {
                    cc.director.loadScene('success');
                }
            }
        }
    },

    initTiles(tileWidth) {
        this.tileLayer.removeAllChildren();
        this.tiles = [];
        this.zeroTiles = [];
        for (let x = 0; x < 4; x++) {
            this.tiles[x] = [];
            for (let y = 0; y < 4; y++) {
                let tileNode = cc.instantiate(this.tilePrefab);
                this.tileLayer.addChild(tileNode);
                tileNode.x = x * this.tileWidth + this.tileWidth / 2;
                tileNode.y = y * this.tileWidth + this.tileWidth / 2;
                let tile = tileNode.getComponent('Tile');
                tile.init(x, y, 0);
                this.tiles[x][y] = tile;
                this.zeroTiles.push(tile);
            }
        }
        for (let i = 0; i < 2; i++) {
            this.newTile();
        }
    },

    newTile() {
        this.zeroTiles = [];
        for (let x = 0; x < 4; x++) {
            for (let y = 0; y < 4; y++) {
                if (this.tiles[x][y].number === 0) {
                    this.zeroTiles.push(this.tiles[x][y]);
                }
            }
        }
        let n = Math.floor(Math.random() * this.zeroTiles.length);
        this.zeroTiles[n].randomNumber();
        // this.zeroTiles[n].getComponent('Tile').randomNumber();
        this.zeroTiles.splice(n, 1);
    },

    onBtnRetry() {
        cc.director.loadScene('game');
    },

    onBtnSleep() {
        cc.director.loadScene('sleep');
    }

});






//---------------Tile.js------------------------

cc.Class({
    extends: cc.Component,

    properties: {
        x: 0,
        y: 0,
        _number: 0,
        number: {
            set(number) {
                if (number === this._number) return;
                this._number = number;
                if (number === 0) {
                    this.numberLabel.string = '';
                } else {
                    this.numberLabel.string = number + '';
                    // let colorHex = Math.floor(Math.random() * 16777215) + 1;
                    // let color = cc.hexToColor('#' + colorHex.toString(16));
                    // this.node.color = color;
                    if(this.number > 0) {
                        this.node.color = cc.Color.RED;
                    }else{
                        this.node.color = cc.Color.BLUE;
                        // this.node.color = cc.Color.GREEN;
                    }
                }
            },
            get() {
                return this._number;
            }
        },
        numberLabel: cc.Label,
    },

    // use this for initialization
    onLoad: function () {

    },

    init(x, y, n) {
        this.x = x;
        this.y = y;
        this.number = n;
    },

    randomNumber() {
        this.number = 2;
        // let n = Math.ceil(Math.random() * 2);
        // if(n === 1) {
        //     this.number = 64;
        // }else {
        //     this.number = -64;
        // }
    }
});





//---------------GameScene.js------------------------


cc.Class({
    extends: cc.Component,

    properties: {
        // foo: {
        //    default: null,      // The default value will be used only when the component attaching
        //                           to a node for the first time
        //    url: cc.Texture2D,  // optional, default is typeof default
        //    serializable: true, // optional, default is true
        //    visible: true,      // optional, default is true
        //    displayName: 'Foo', // optional
        //    readonly: false,    // optional, default is false
        // },
        // ...
    },

    // use this for initialization
    onLoad: function () {

    },

    // called every frame, uncomment this function to activate update callback
    // update: function (dt) {

    // },
});












感谢:

本文转载自https://mp.weixin.qq.com/s/7sqizrU-hZmPOcweK0yPHQ这篇文章,这里感谢原作者对于技术的分享。

下载:

本文章源码和资源下载地址

发布了265 篇原创文章 · 获赞 20 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ccnu027cs/article/details/103522388