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

(这是本人第一次教程写作之旅,没有什么乱七八糟的套路,就是为了将自己的技术写出来,让大家一同来学习,得以提高自己的水平。由于水平有限,如在过程中发现错误的或者有更好的方法不吝贵读者的评论。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工程的创建过程

image

除创建命令外,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所示。

image

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();
在随机的两个卡片上生成数字,在随机生成的时候我们应该
先判断还有没有空位
,否则有可能会陷入死循环。

初始化的界面如下图:


image

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

你可能感兴趣的:(cocos2d-js 系列教程之2048开发一)