初学者Cocos(TypeScritp)简单实现2048游戏

       因为一些原因最近比较空闲,本来一直以来的目标是想向着Unity大神进发的,抱着毕其一生的心态,毕竟Unity的前景摆在眼前,可现在闲着也是闲着就玩一下Cocos,还用是TypeScript语言,哈哈!在我一个前辈的建议下先做了个程序员都知道的2048小游戏,说真的2048这个游戏我之前就看人玩过,自己从来没有上过手,连规则都不知道。。所以还专门下了个玩了会才开始动手。

原谅我把这个技术博客写成了个人生活日记一般了。。哈哈!真是闲着蛋疼又很久没人没地和人扯淡了,就当在这发泄一下了!既然这么多废话,那我索性把它当作初学者的心得写吧。

用cocos前,当前还是先把整个官方文档都过了一边啦,因为有Unity的开发经验,所以文档里的大部分功能基本都能理解,看起来挺轻松的。然后我就跑去看Js的官方文档了。。。没错。。我还粗略看了一边js文档。。因为我开始并不知道可以用TS,哈哈哈!最后我还是又把TS的官方文档粗略的看完了一边,真的是粗略,甚至还没Js文档看得仔细,我就动手用Ts写这个游戏了。我想,一定是那个啥,二八原则!80%的问题都可以用20%的技术解决,哈哈哈哈!不扯,真正的原因是2048用的Ts语言的东西不多,后面要写复杂的游戏肯定还有坑要踩。

好了先上结果吧:

 

确实是简单的实现,其他UI部分都没有的。

下面上代码:

核心部分

import GameCtrl from './GameCtrl';

const {ccclass, property} = cc._decorator;

@ccclass
export default class GameCore{

    private static _instance : GameCore = null;
    public static Instance():GameCore{
        if(GameCore._instance ===null){
            GameCore._instance = new GameCore();
        }
        return GameCore._instance;
    }

    map : Array<Array<any>> = new Array<Array<any>>();
    mapContrast : Array<Array<any>> = new Array<Array<any>>();
    SpaceAmount : number;    //剩余空格数量

    Init(){

        this.SpaceAmount = 0;

        let x : number = Math.random() * 4;
        let y : number = Math.random() * 4;

        x = Math.floor(x);
        y = Math.floor(y);

        for(let i=0; i < 4; i ++)
        {
            this.map[i] = [];
            this.mapContrast[i] = [];
            for(let j=0; j < 4; j ++)
            {
                this.map[i][j] = 0;
                this.mapContrast[i][j] = 0;
            }
        }
        
        console.log(x +" <---> " + y);
        this.map[x][y] = 2;
        this.mapContrast[x][y] = 2;

        GameCtrl.ShowUI(this.map);

        this.map.forEach((val,idx,array)=>{

            console.log(idx +" --- " + val);
        });
    }

    onKeyUp(event){

        //console.log("uppppppp");
        this.SpaceAmount = 0;
        switch(event.keyCode)
        {
            case cc.macro.KEY.up:
            this.MergeToUp();
            break;

            case cc.macro.KEY.down:
                this.MergeToDown();
            break;

            case cc.macro.KEY.left:
                this.MergeToLeft();
            break;

            case cc.macro.KEY.right:
                this.MergeToRight();
            break;
        
        }
        this.AddNewNumber();

        GameCtrl.ShowUI(this.map);

        this.map.forEach((val, idx, ar)=>{
    
            console.log(idx +" === " + val);
        });
    }

    //增加新数字
    AddNewNumber(){

        if(this.SpaceAmount == 0)
        {
            GameCtrl.Instance().GameOver();
            return;
        }

        let isCanAdd = false;
        
        let dic: { [key: number]: cc.Vec2; } = {};
        let idx = 0;

        for(let i =0; i < 4; i++)
        {
            for(let j = 0; j < 4; j++)
            {
                if(this.map[i][j] == 0)
                {
                    //记录空白处的XY,即数组中空白处的xy值
                    dic[idx] = new cc.Vec2(i, j);
                    idx +=1;
                }
                if(this.map[i][j] != this.mapContrast[i][j])
                {
                    //和记录的对照数组做对比,与上一次的数组出现不同则说明可以增加数字
                    isCanAdd = true;
                }
            }
        }

        if(isCanAdd)
        {
            //随机
            let randomIdx = Math.floor(Math.random() * idx);
            //前提是存在空白的xy
            if(dic != null && dic.hasOwnProperty(randomIdx))
            {
                this.map[dic[randomIdx].x][dic[randomIdx].y] = 2;
                console.log(" ## random add --> " + dic[randomIdx].x + dic[randomIdx].y);
            }
        }
    }

    MergeToUp(){
        for(let i = 0; i < 4; i++)
        {
            let temp : number[] = [0,0,0,0];
            
            for(let j=0; j < 4; j++)
            {
                temp[j] = this.map[j][i];
            }

            //重新赋值每列的数
            let newArr = this.MergeArr(temp);

            for(let k = 0; k < 4; k++)
            {
                this.map[k][i] = newArr[k];
            }

        }

        // this.map.forEach((val, idx, ar)=>{

        //     console.log(idx +" === " + val);

        // });
    }

    MergeToDown(){
        for(let i = 0; i < 4; i++)
        {
            let temp : number[] = [0,0,0,0];
            
            let tempidx = 0;
            for(let j= 3; j >=0; j--)
            {
                temp[tempidx] = this.map[j][i];
                tempidx +=1;
            }

            //重新赋值每列的数
            let newArr = this.MergeArr(temp);

            tempidx = 0;
            for(let k = 3; k >=0; k--)
            {
                this.map[k][i] = newArr[tempidx];
                tempidx +=1;
            }

        }

        // this.map.forEach((val, idx, ar)=>{

        //     console.log(idx +" === " + val);

        // });
    }

    //向左合并
    MergeToLeft(){

        for(let i = 0; i < 4; i ++)
        {
            //重新赋值每列的数
            this.map[i] = this.MergeArr(this.map[i]);
        }

        // this.map.forEach((val, idx, ar)=>{

        //     console.log(idx +" === " + val);

        // });
    }

    //向右合并
    MergeToRight(){

        for(let i = 0; i < 4; i++)
        {
            let temp : number[] = [0,0,0,0];
            
            let tempidx = 0;
            for(let j = 3; j >=0; j--)
            {
                temp[tempidx] = this.map[i][j];
                tempidx +=1;
            }

            //重新赋值每列的数
            let newArr = this.MergeArr(temp);

            tempidx = 0;
            for(let k = 3; k >=0; k--)
            {
                this.map[i][k] = newArr[tempidx];
                tempidx +=1;
            }

        }

        // this.map.forEach((val, idx, ar)=>{
    
        //     console.log(idx +" === " + val);
    
        // });
    }

    //核心合并
    MergeArr (arr : Array<Number>)
    {
        let myArr : Array<Number> = [0,0,0,0];
        let myArrIdx = 0;
        let isCompara = false;

        for(let i = 0; i < 4; i ++)
        {
            if(arr[i] >0)
            {
                if(isCompara)
                {
                    //可以比较则比较是否相等
                    if(myArr[myArrIdx -1] == arr[i])
                    {
                        myArr[myArrIdx -1] = (arr[i] as number) * 2;
                        isCompara = false;
                        continue;
                    }
                }
                myArr[myArrIdx] = arr[i];
                myArrIdx +=1;
                //新加入的数字,可以进行比较
                isCompara = true;
            }
        }

        //记录空格数量
        this.SpaceAmount += 4 - myArrIdx;
        
        return myArr;   
    }

}

游戏控制部分

import GameCore from './GameCore';
import ShopCtrl from './ShopCtrl';

const {ccclass, property} = cc._decorator;

@ccclass
export default class GameCtrl extends cc.Component {

    private static _instance : GameCtrl = null;
    public static Instance():GameCtrl{
        return GameCtrl._instance;
    }

    @property(cc.Node)
    shopsRoot : cc.Node = null;

    // @property(cc.Label)
    // allShops : cc.Label[] = [];

    showShops: cc.Label[] = [];

    shopCtrls : ShopCtrl[] = [];

    onLoad () {

        GameCtrl._instance = this;
        //获取所有shopLab
        this.showShops = this.shopsRoot.getComponentsInChildren(cc.Label);
        this.shopCtrls = this.shopsRoot.getComponentsInChildren(ShopCtrl);

        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP,this.onKeyUp, this);
        // FBInstant
        
    }

    start()
    {
        GameCore.Instance().Init();
    }

    onDestroy(){
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP,this.onKeyUp, this);
    }

     
    onKeyUp(event){

        console.log("uppppppp");
        GameCore.Instance().SpaceAmount = 0;
        switch(event.keyCode)
        {
            case cc.macro.KEY.up:
                GameCore.Instance().MergeToUp();
            break;

            case cc.macro.KEY.down:
                GameCore.Instance().MergeToDown();
            break;

            case cc.macro.KEY.left:
                GameCore.Instance().MergeToLeft();
            break;

            case cc.macro.KEY.right:
                GameCore.Instance().MergeToRight();
            break;
        
        }
        GameCore.Instance().AddNewNumber();

        GameCtrl.ShowUI(GameCore.Instance().map);
        
        // GameCore.Instance.map.forEach((val, idx, ar)=>{
    
        //     console.log(idx +" === " + val);
    
        // });
    }

    GameOver(){
        console.log(" ~~~~~ game over ~~~~~");
    }

    static ShowUI(Arr : Array<Array<any>>){

        let idx = 0;
        for(let i = 0; i < 4; i++)
        {
            for(let j = 0; j < 4; j ++)
            {
                //this._instance.showShops[idx].string = Arr[i][j];
                this._instance.shopCtrls[idx].showNumber(Arr[i][j]);
                idx +=1;
            }
        }
    }

    // update (dt) {}
}

方格控制脚本,我习惯每个方格挂脚本,传参数让它自己管理


const {ccclass, property} = cc._decorator;

@ccclass
export default class ShopCtrl extends cc.Component {

    label: cc.Label = null;

    // @property(cc.Sprite)
    bg: cc.Node = null;

    // LIFE-CYCLE CALLBACKS:

    onLoad () {

        this.label = this.node.getComponentInChildren(cc.Label);
        this.bg = this.node;
        
    }

    showNumber(number : number)
    {
        this.label.string = number.toString();

        let col = cc.Color.WHITE;

        switch(number)
        {
            case 0 :

            break;
            case 2 :
            col = cc.Color.YELLOW;
            break;
            case 4 :
            col = cc.Color.BLUE;
            break;
            case 8 :
            col = cc.Color.CYAN;
            break;
            case 16 :
            col = cc.Color.GRAY;
            break;
            case 32:
            col = cc.Color.GREEN;
            break;
            case 64:
            col = cc.Color.MAGENTA;
            break;
            case 128:
            col = cc.Color.ORANGE;
            break;
            case 256:
            col = cc.Color.RED;
            break;
            case 512:
            col = cc.Color.YELLOW;
            break;
            case 1024:
            col = cc.Color.GREEN;
            break;
            case 2048:
            col = cc.Color.TRANSPARENT;
            break;

        }
      
        this.bg.color = col;

    }
}

最后,结束本并没有很好的做好判断,只是粗略的写了下。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sam_ONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值