利用cocos2dx 3.2开发消灭星星(四)游戏主场景

第二节说到在菜单场景MenuScene中加入一个菜单并且加入一个开始按钮切换到GameScene,下面我们来讲一下游戏的主界面GameScene和GameLayer
一、主场景GameScene
GameScene.h

class GameScene : public Scene{
public:
    virtual bool init();
    CREATE_FUNC(GameScene);
};

```

GameScene.cpp
bool GameScene::init(){
    if(!Scene::init()){
        return false;
    }
    Audio::getInstance()->playBGM();
    this->addChild(GameLayer::create());
    return true;
} 

```

GameScene很简单,里面只有一个GameLayer层。注意Audio是我们的音效工具,我们以后再说
我们主要看一下GameLayer
二、GameLayer
头文件GameLayer.h
class GameLayer : public Layer{
public:
    virtual bool init();
    CREATE_FUNC(GameLayer);
    void floatLevelWord();    //飘出关卡信息
    void floatTargetScoreWord();    //飘出目标分数
    void removeFloatWord();    //移除关卡信息和目标分数
    void showStarMatrix();    //创造星星矩阵(所有的星星)
    virtual void update(float delta);//update
    virtual bool onTouchBegan(Touch* touch,Event* event);//接受触摸事件
    void refreshMenu();    //刷新顶部信息
    void showLinkNum(int size);    //显示连击信息
    void hideLinkNum();    //隐藏连击信息
    void floatLeftStarMsg(int leftNum);    //显示剩余星星数量
    void gotoNextLevel();    //跳到另一关
    void gotoGameOver();    //游戏结束
private:
    FloatWord* _levelMsg;    //关卡信息(飘字)
    FloatWord* _targetScore;    //目标分数(飘字)
    TopMenu* menu;    //顶部信息
    StarMatrix* matrix;    //所有星星
    Label* linkNum;    //连击信息
};

```

GameLayer好像定义了许多东西,但是我们可以从下面的私有成员可以看到,其实GameLayer就包含了4个组件。
1)关卡和目标分数信息(Layer刚启动时的飘字)
2)顶部信息栏
3)矩阵的布局(就是所有的星星)
4)连击的信息
除了onTouchBegan和update这两个函数,其余函数基本都是为这4个组件添加功能。
onTouchBegan是触摸事件发生的回调函数。
update是每帧刷新调用的回调函数。

下面我们分别对这四个组件解读。
1._levelMsg 和 _targetScore 为了实现先飘入关卡信息,再飘入目标分数,等两条信息飘出后才显示_matrix(所有的星星)
具体实现
1)在GameLayer的init函数里面调用floatLevelWord函数
this->floatLevelWord();

```

2)floatLevelWord飘出关卡字体(FloatWord的floatIn方法,具体见第三节)
void GameLayer::floatLevelWord(){
    Size visibleSize = Director::getInstance()->getVisibleSize();
    _levelMsg = FloatWord::create(
        ChineseWord("guanqia") + cocos2d::String::createWithFormat(": %d",GAMEDATA::getInstance()->getNextLevel())->_string,
        50, Point(visibleSize.width,visibleSize.height/3*2)
        );
    this->addChild(_levelMsg,1);
    _levelMsg->floatIn(0.5f,CC_CALLBACK_0(GameLayer::floatTargetScoreWord,this));
    Audio::getInstance()->playReadyGo();
}

```

3)_levelMsg 的floatIn后的回调是floatTargetScoreWord
void GameLayer::floatTargetScoreWord(){
    Size visibleSize = Director::getInstance()->getVisibleSize();
    _targetScore = FloatWord::create(
        ChineseWord("mubiao") + cocos2d::String::createWithFormat(": %d",GAMEDATA::getInstance()->getNextScore())->_string + ChineseWord("fen"),
        50, Point(visibleSize.width,visibleSize.height/3)
        );
    this->addChild(_targetScore,1);
    _targetScore->floatIn(0.5f,CC_CALLBACK_0(GameLayer::removeFloatWord,this));
}

```

4)_targetScore的floatIn后的回调是removeFloatWord,用于移除_levelMsg 和_targetScore
void GameLayer::removeFloatWord(){
    _levelMsg->floatOut(0.5f,nullptr);
    _targetScore->floatOut(0.5f,CC_CALLBACK_0(GameLayer::showStarMatrix,this));
}

```

5)同样,_levelMsg或_targetScore的floatOut后调用showStarMatrix,用于显示星星矩阵(所有星星)
void GameLayer::showStarMatrix(){
    matrix = StarMatrix::create(this);
    this->addChild(matrix);
}

```

至此,从进入GameLayer -> 飘出关卡信息(floatLevelWord)->飘出目标分数(floatTargetWord) -> 移除(removeFloatWord)->显示星星矩阵(showStarMatrix)的流程结束。

这里提到了StarMatrix这个类。我们就先讲一下单个星星的Star类
Star类就是单颗星星的包装,主要包括星星的颜色,星星的当前位置,星星的目标位置(为什么星星有两个位置?这个等下说),以及星星在矩阵中的位置(与星星矩阵相关)
class Star : public Sprite{
public:
    enum color{
        GREEN,
        RED,
        YELLOW,
        PURPLE,
        BLUE
    };
    static Star* create(int color);
    int getColor();
    void setDesPosition(const Point& p);
    inline Point getDesPosition(){return desPosition;}
    void updatePosition();
    inline int getIndexI(){return index_i;}
    inline int getIndexJ(){return index_j;}
    inline void setIndex_ij(int i,int j){index_i = i;index_j = j;}
private:
    char* getImage(int color);

public:
    static const int COLOR_MAX_NUM = 5;
    static const int STAR_WIDTH = 48;
    static const int STAR_HEIGHT = 48;
private:
    int color;
    Point desPosition;
    bool selected;
    int index_i;
    int index_j;
};

```

这里需要注意的有两点:1,create函数需要传入一个int值代表星星的颜色
    2,getImage函数就是通过传入的代表星星颜色的int值找到对应的图片
下面是create和getImage的代码
Star* Star::create(int color){
    Star* ret = new Star();
    if(ret && ret->initWithFile(ret->getImage(color))){
        ret->color = color;
        ret->selected = false;
        ret->autorelease();
        return ret;
    }
    CC_SAFE_DELETE(ret);
    return nullptr;
}

char* Star::getImage(int color){
    switch(color){
    case color::BLUE:
        return "blue.png";
    case color::GREEN:
        return "green.png";
    case color::YELLOW:
        return "orange.png";
    case color::RED:
        return "red.png";
    case color::PURPLE:
        return "purple.png";
    }
}

```

这样,我们在构造单颗星星的时候,只需要向create函数传入一个数字,就能够构造出不同颜色的星星。

好了,这样我们就大致讲完单颗星星Star类,我们再回过头来看StarMatrix
先看StarMatrix的代码
class StarMatrix : public Node{
public:
    static StarMatrix* create(GameLayer* layer);
    virtual bool init(GameLayer* layer);
     void initMatrix();
public:
    const static int ROW_NUM = 10;
    const static int COL_NUM = 10;
private:
    Star* stars;
    GameLayer* m_layer;
};

```

这里大家可以发现,StarMatrix其实就是对一个Star*二维数组的包装,但是这里要注意一下,StarMatrix的构造需要传入Layer(这个是为了以后通知layer进行更新操作用)
StarMatrix的init函数会调用initMatrix()方法,而initMatrix()方法实质就是初始化内置的Star*二维数组
void StarMatrix::initMatrix(){
    srand(time(0));
    for(int i=0;i<ROW_NUM;i++){
        for(int j=0;jsetPosition(getPositionByIndex(i,j) + Point(0,100));
            star->setDesPosition(getPositionByIndex(i,j));
            star->setIndex_ij(i,j);
            this->addChild(star);
        }
    }
}

```

1)在构造星星的时候用了随机数(应该不难想到吧)
2)初始化的时候同时对Star的一些属性进行设置(当前位置,目标位置,在矩阵中的位置)
3)getPointionByIndex是我自己写的一个可以由矩阵位置i和j得到一个Point的一个函数,下面给出代码
Point StarMatrix::getPositionByIndex(int i,int j){
    float x = j * Star::STAR_WIDTH + Star::STAR_WIDTH/2;
    float y = (StarMatrix::COL_NUM - i)*Star::STAR_HEIGHT - Star::STAR_HEIGHT/2;
    return Point(x,y);
}

```

其实就是由i和j得到像素位置的方法,很简单

至于这里再次出现了当前位置和目标位置,这两个位置有什么用?我们下一节再讨论,暂时可以先把他们先设置成一下。

至此,从进入GameLayer -> 飘出关卡信息(floatLevelWord)->飘出目标分数(floatTargetWord) -> 移除(removeFloatWord)->显示星星矩阵(showStarMatrix)的流程结束。
效果如下:
飘字

![](http://img.blog.csdn.net/20140910204416968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGV6aWppYW4yMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)

飘字结束显示的星星矩阵


![](http://img.blog.csdn.net/20140910204706410?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGV6aWppYW4yMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)