美文网首页
cocos2d-js 系列教程之2048开发一

cocos2d-js 系列教程之2048开发一

作者: 很前端的前端 | 来源:发表于2017-02-05 17:39 被阅读0次

    (这是本人第一次教程写作之旅,没有什么乱七八糟的套路,就是为了将自己的技术写出来,让大家一同来学习,得以提高自己的水平。由于水平有限,如在过程中发现错误的或者有更好的方法不吝贵读者的评论。2017 撸起袖子干!联系方式:qq: 785861210. )


    一、介绍

    cocos2d-JS是cocos2d-x (官网 :http://cocos2d-x.org/) 的JavaScript版本,它的前身是cocos2d-html5。在3.0版本以前叫做cocos2d-html5,从3.0版本开始叫做cocos2d-JS。我们知道cocos2d-x支持使用C++、Lua、Javascript来进行程序开发,其所内置的是一个Javascript引擎,通过用C++解析Javascript去执行;而cocos2d-html5是使用Javascript进行开发,最终运行在浏览器里的。那么在v3.0的时候,cocos2d-html5和cocos2d-x JSBinding被合到了一起,称作cocos2d-JS。和cocos2d-html5不同的是,cocos2d-JS开发的程序不仅可以运行在浏览器里,还可以编译运行在Mac OSX, Windows, iOS, Android的原生平台上,真正做到“一次开发,全平台运行”。cocos2d-JS支持cocos2d-x的所有特性并提供更简单易用的Javascript风格API,它还自带了cocos Console,一个用于简化项目创建和不同目标平台编译发布流程的终端工具。


    二、2048游戏开发

    1. 创建项目 (默认读者已经搭建好一系列的开发环境)

    通过如下命令创建一个名为game2048的工程

    cocos new game2048 -l js
    

    其中,-l表示采用的语言,可选值为cpp、lua以及js。运行命令之后,便可在所在目录看到game2048文件夹。
    图1-1为game2048工程的创建过程

    imageimage

    除创建命令外,cocos console还为工程提供了运行、编译等命令,具体如下:
    a. cocos run -p web|ios|android|mac|win32 //运行在指定平台
    b. cocos compile -p web|ios|android|mac|win32 -m release//将项目工程打包到指定平台上

    2. 项目game2048的目录结构

    打开刚刚创建好的game2048工程,可以看到其目录结构图如图1-2所示。

    imageimage

    3. 创建游戏场景

    由于2048游戏相对简单,它只需要一个场景,下面我们来创建一个场景:

    //层
    var gameLayer = cc.Layer.extend({
        sprite:null,
        ctor:function () {
            this._super();
    
            return true;
        }
    });
    //场景
    var gameScene = cc.Scene.extend({
        onEnter:function () {
            this._super();
            var _gameLayer = new gameLayer();
            this.addChild(layer);
        }
    });
    

    很简单吧!我们只需要创建一个Layer类,然后将它的一个实例加入Scene中,程序运行时main.js会创建一个Scene的实例作为程序入口。

    4. 创建卡牌类

    我们把2048游戏中的每一个方格看作一个卡片,上面的数字是它的属性。也就是说我们需要4x4=16个卡片类的对象。新建一个CardSprite.js文件:

    var CardSprite = cc.Layer.extend({
        number:0,
        labelCardNumber:null,
        cardColorBG:null,
        ctor:function(){
            this._super();
        },
        initCard:function(num, width, height, positionX, positionY){
            this.number = num;
    
            this.cardColorBG = new cc.LayerColor(new cc.color(200, 190, 180, 255), width-15, height-15);
            this.cardColorBG.setPosition(positionX, positionY);
    
            if(this.number > 0){
                this.labelCardNumber = new cc.LabelTTF(this.number,"Arial", 60);
                this.labelCardNumber.setPosition(this.cardColorBG.getContentSize().width/2, this.cardColorBG.getContentSize().height/2);
                this.labelCardNumber.setTag(8);
                this.cardColorBG.addChild(this.labelCardNumber);
            }else{
                this.labelCardNumber = new cc.LabelTTF(" ","Arial", 60);
                this.labelCardNumber.setPosition(this.cardColorBG.getContentSize().width/2, this.cardColorBG.getContentSize().height/2);
                this.labelCardNumber.setTag(8);
                this.cardColorBG.addChild(this.labelCardNumber);
            }
            this.addChild(this.cardColorBG);
        },
        getNumber:function(){
            return this.number;
        },
        setNumber:function(num){
            this.number = num;
            if(this.number > 0){
                this.labelCardNumber.setString(this.number);
            }else{
                this.labelCardNumber.setString("");
            }
            // 设置数字大小
            if(num >= 0){
                this.labelCardNumber.setFontSize(60);
            }
            if(num >= 16){
                this.labelCardNumber.setFontSize(55);
            }
            if(num >= 128){
                this.labelCardNumber.setFontSize(40);
            }
            if(num >= 1024){
                this.labelCardNumber.setFontSize(30)
            }
            //判断数字的大小来调整颜色
            if(this.number == 0){
                this.cardColorBG.setColor(new cc.color(200,190,180));
            }
            if (this.number == 2) {
                this.cardColorBG.setColor(new cc.color(240,230,220));
            }
            if (this.number == 4) {
                this.cardColorBG.setColor(new cc.color(240,220,200));
            }
            if (this.number == 8) {
                this.cardColorBG.setColor(new cc.color(240,180,120));
            }
            if (this.number == 16) {
                this.cardColorBG.setColor(new cc.color(240,140,90));
            }
            if (this.number == 32) {
                this.cardColorBG.setColor(new cc.color(240,120,90));
            }
            if (this.number == 64) {
                this.cardColorBG.setColor(new cc.color(240,90,60));
            }
            if (this.number == 128) {
                this.cardColorBG.setColor(new cc.color(240,90,60));
            }
            if (this.number == 256) {
                this.cardColorBG.setColor(new cc.color(240,200,70));
            }
            if (this.number == 512) {
                this.cardColorBG.setColor(new cc.color(240,200,70));
            }
            if (this.number == 1024) {
                this.cardColorBG.setColor(new cc.color(0,130,0));
            }
            if (this.number == 2048) {
                this.cardColorBG.setColor(new cc.color(0,130,0));
            }
        }
    });
    
    // 静态函数
    CardSprite.createCardSprite = function(num, width, height, positionX, positionY)
    {
        var card = new CardSprite();
        if(card){
            card.initCard(num, width, height, positionX, positionY);
            return card;
        }
        return null;
    }
    

    这里将CardSprite类继承自Layer,然后初始化卡片背景和上面的数字,还定义了number的set/get方法。这里需要注意几点:
    新建.js文件以后需要在project.json相关位置添加文件路径。
    继承都需要有 this._super();,一般写在构造函数ctor:function()中。
    注意静态函数的写法,类名.函数名 = function(){}。

    5. 初始化游戏界面

    主要是在Layer的init()函数中初始化,我们使用一个4x4的二维组来放置在主界面创建16个卡片:

    var gameLayer = cc.Layer.extend({
        name : 'gameLayer',
        firstX:null,
        firstY:null,
        cardArr:null,
        score:0,
        scoreLabel:null,
        gameOverLayer:null,
        gameWinLayer:null,
        ctor : function(){
            this._super();
    
            this.init();
    
            this.ignoreAnchorPointForPosition(false);
    
            this.initContent();
    
            this.loadListener();
        },
        init : function(){
            var gameBg  = new cc.Sprite(res.loadingpage);
            gameBg.x = size.width/2;
            gameBg.y = size.height/2;
            this.addChild(gameBg,0);
        },
        initContent : function(){
            var lazyLayer = this.lazyLayer = new cc.LayerColor(cc.color(180, 170, 160, 255), 560, 560);
            lazyLayer.ignoreAnchorPointForPosition(false);
            lazyLayer.x = size.width/2;
            lazyLayer.y = size.height/2;
            this.addChild(lazyLayer);
    
            // 显示分数
            var label = new cc.LabelTTF("Score : ", "Arial", 32);
            label.fillStyle = cc.color.RED;
            label.setAnchorPoint(0,0);
            label.x = 100;
            label.y = size.height - 100;
            this.addChild(label, 10);
            this.scoreLabel = new cc.LabelTTF("0", "Arial", 32);
            this.scoreLabel.setAnchorPoint(0,0);
            this.scoreLabel.x = 100 + 120;
            this.scoreLabel.y = size.height - 100;
            this.addChild(this.scoreLabel, 10);
    
            // 创建卡片数组
            this.cardArr = new Array(4);
            for(var i=0; i<4; i++)
            {
                this.cardArr[i] = new Array(4);
            }
    
            var _size = cc.director.getWinSize();
            // 初始化卡片数组
            this.createCards(_size);
    
            // 随机生成两个数字
            this.autoCreateCardNumber();
            this.autoCreateCardNumber();
        },
        createCards:function(size){
            var unitSize = (size.height/2 - 80)/4;
            var unitSizeY = unitSize - 30;
            for(var i=0; i<4; i++){
                for(var j=0; j<4; j++){
                    var card = CardSprite.createCardSprite(0, unitSize, unitSize, unitSize*i + 80, unitSize*j + 330);
                    this.cardArr[i][j] = card;
                    this.addChild(card);
                }
            }
        },
        autoCreateCardNumber:function(){//生成随机的卡片,数字2/4
            while(1){
                var i = Math.floor(Math.random()*4);  // generate a number between 0 and 3
                var j = Math.floor(Math.random()*4);
    
                if (this.cardArr[i][j].getNumber() == 0){
                    this.cardArr[i][j].setNumber(Math.floor(Math.random()*10) < 1 ? 4 : 2);
                    break;
                }
    
                if (!this.shouldCreateCardNumber()){
                    break;
                }
            }
        },
        shouldCreateCardNumber:function(){// 判断是否需要自动生成新的卡片
            var should = false;
            for(var i=0; i<4; ++i){
                for(var j=0; j<4; ++j){
                    if (this.cardArr[i][j].getNumber() == 0){
                        should = true;
                        break;
                    }
                }
            }
            return should;
        }
    });
    var gameScene = cc.Scene.extend({
        ctor:function(){
            this._super();
    
            var layer = new gameLayer();
            this.addChild(layer);
            layer.x = size.width/2;
            layer.y = size.height/2;
        }
    });
    

    通过调用
    this.createCards(size);
    初始化所有16个卡片,由于0不显示,所以卡片上都没有数字。然后调用
    this.autoCreateCardNumber();
    在随机的两个卡片上生成数字,在随机生成的时候我们应该
    先判断还有没有空位
    ,否则有可能会陷入死循环。

    初始化的界面如下图:


    imageimage

    今天就先到这里啦~~~(下节内容定义手势动作,卡片合并,添加分数,判断游戏结束和顺利,界面优化)下节继续,下节再见!

    相关文章

      网友评论

          本文标题:cocos2d-js 系列教程之2048开发一

          本文链接:https://www.haomeiwen.com/subject/jcveittx.html