Flappy Bird

守給你的承諾、 提交于 2020-02-04 19:23:45

Flappy Bird

尊重原创,源码取自:https://github.com/OiteBoys/Earlybird

(一) 文件的读取

  游戏中非常重要的元素---图片,所以先从图片下手。

  由于所有的图片资源都是放在一张大图上的,切割图片保存的又不是plist文件,所以在这里模拟SpriteFrameCache写了一个AtlasLoader类,该类主要功能用于缓存图片。

AtlasLoader.h

 1 #pragma once
 2 #include "cocos2d.h"
 3 
 4 using namespace cocos2d;
 5 using namespace std;
 6 
 7 // 图片信息结构体,主要用于保存图片
 8 typedef struct _atlas{
 9     char name[255];
10     int width;
11     int height;
12     Point start;
13     Point end;
14 } Atlas;
15 
16 class AtlasLoader{
17 public:
18     // 获取单例
19     static AtlasLoader* getInstance();
20 
21     // 销毁单例
22     static void destroyInstance();
23 
24     /**
25     * 加载文件
26     * 这个函数加载图片,会延迟主线程
27     * 例: AtlasLoader::getInstance()->loadAtlas("atlas.txt");
28     */
29     void loadAtlas(string filename);
30 
31     /**
32     * 加载文件
33     * 可以在异步加载纹理的回调函数中调用该函数
34     */
35     void loadAtlas(string filename, Texture2D *texture);
36 
37     /**
38     * 通过名字获取精灵帧,用于创建精灵
39     * 提示:应该在用getTextureCache加载atlas.png完成之后调用该函数
40     * 例如. SpriteFrame *bg_day = AtlasLoader::getInstance()->getSpriteFrameByName("bg_day");
41     */
42     SpriteFrame* getSpriteFrameByName(string name);
43 
44 protected:
45     /**
46      *  默认构造函数
47      */
48     AtlasLoader();
49     
50     /**
51      *  初始化 
52      */
53     virtual bool init();
54 
55     /**
56      * 单例指针
57      */
58     static AtlasLoader* sharedAtlasLoader;
59 
60     /**
61     *  用于保存精灵帧的MAP<std::string 名字,SpriteFrame* 精灵帧指针>
62     */
63     Map<std::string, SpriteFrame*> _spriteFrames;
64 };

AtlasLoader.cpp

 1 #include "AtlasLoader.h"
 2 
 3 // 初始化单例指针(因为是静态变量,所以在这里初始化)
 4 AtlasLoader* AtlasLoader::sharedAtlasLoader = nullptr;
 5 
 6 AtlasLoader* AtlasLoader::getInstance(){
 7     if(sharedAtlasLoader == NULL) {
 8         sharedAtlasLoader = new AtlasLoader();
 9         if(!sharedAtlasLoader->init()){
10             delete sharedAtlasLoader;
11             sharedAtlasLoader = NULL;
12             CCLOG("ERROR: Could not init sharedAtlasLoader");
13         }
14     }
15     return sharedAtlasLoader;
16 }
17 
18 void AtlasLoader::destroyInstance()
19 {
20     CC_SAFE_DELETE(sharedAtlasLoader);
21 }
22 
23 AtlasLoader::AtlasLoader(){}
24 
25 
26 bool AtlasLoader::init(){
27     return true;
28 }
29 
30 void AtlasLoader::loadAtlas(string filename){
31     // 获取一张纹理
32     auto textureAtlas = Director::getInstance()->getTextureCache()->addImage("atlas.png");
33     // 加载文件
34     this->loadAtlas(filename, textureAtlas);
35 }
36 
37 void AtlasLoader::loadAtlas(string filename, Texture2D *texture) {
38     // 读取文件
39     string data = FileUtils::getInstance()->getStringFromFile(filename);
40 
41     unsigned pos;
42     Atlas atlas;
43     pos = data.find_first_of("\n");
44     string line = data.substr(0, pos);
45     data = data.substr(pos + 1);
46     while(line != ""){
47         sscanf(line.c_str(), "%s %d %d %f %f %f %f", 
48         atlas.name, &atlas.width, &atlas.height, &atlas.start.x, 
49         &atlas.start.y, &atlas.end.x, &atlas.end.y);
50         atlas.start.x = 1024*atlas.start.x;
51         atlas.start.y = 1024*atlas.start.y;
52         atlas.end.x = 1024*atlas.end.x;
53         atlas.end.y = 1024*atlas.end.y;
54 
55         pos = data.find_first_of("\n");
56         line = data.substr(0, pos);
57         data = data.substr(pos + 1);
58 
59         // use the data to create a sprite frame
60         // fix 1px edge bug
61         if(atlas.name == string("land")) {
62             atlas.start.x += 1;
63         }
64 
65         Rect rect = Rect(atlas.start.x, atlas.start.y, atlas.width, atlas.height);
66         auto frame = SpriteFrame::createWithTexture(texture, rect);        // 通过纹理创建精灵帧
67         this->_spriteFrames.insert(string(atlas.name), frame);            // 插入到MAP中
68     }
69 }
70 
71 SpriteFrame* AtlasLoader::getSpriteFrameByName(string name){
72     return this->_spriteFrames.at(name);
73 }

 

(二) LoadingScene(加载场景)

  完成图片缓存之后,我们真正的开始游戏。启动游戏的第一个场景LoadingScene。

  ---> 异步加载图片

  ---> 加载声音

  ---> 场景跳转

 LoadingScene.h

 1 #include "cocos2d.h"
 2 #include "AtlasLoader.h"
 3 #include "SimpleAudioEngine.h"
 4 #include "HelloWorldScene.h"
 5 #include "WelcomeScene.h"
 6 #include "BackgroundLayer.h"
 7 
 8 using namespace cocos2d;
 9 using namespace CocosDenshion;
10 
11 class LoadingScene : public Scene {
12 public:
13     /**
14      * 默认构造
15      */
16     LoadingScene();
17     
18     ~LoadingScene();
19     
20     /**
21      *  初始化
22      */
23     virtual bool init();
24     
25     /* 提供一个create方法,并且返回该类的指针
26     static __TYPE__* create() \
27     { \
28         __TYPE__ *pRet = new __TYPE__(); \
29         if (pRet && pRet->init()) \
30         { \
31             pRet->autorelease(); \
32             return pRet; \
33         } \
34         else \
35         { \
36             delete pRet; \
37             pRet = NULL; \
38             return NULL; \
39         } \
40     }
41     */
42     CREATE_FUNC(LoadingScene);
43     
44     /**
45      * 该类被载入场景的时候被调用,可能会发生多次
46      */
47     void onEnter() override;
48     
49 private:
50     /**
51      * 异步加载纹理完成之后的回调函数
52      */
53     void loadingCallBack(Texture2D *texture);
54 };

LoadingScene.cpp

 1 #include "LoadingScene.h"
 2 LoadingScene::LoadingScene(){}
 3 
 4 LoadingScene::~LoadingScene(){}
 5 
 6 bool LoadingScene::init() {
 7     if(Scene::init()){
 8         return true;
 9     } else {
10         return false;
11     }
12 }
13 
14 void LoadingScene::onEnter(){
15     // 给当前场景添加背景
16     Sprite *background = Sprite::create("splash.png");
17     Size visibleSize = Director::getInstance()->getVisibleSize();
18     Point origin = Director::getInstance()->getVisibleOrigin();
19     background->setPosition(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2);
20     this->addChild(background);
21 
22     // 开始异步加载 atlas.png
23     Director::getInstance()->getTextureCache()->addImageAsync("atlas.png", CC_CALLBACK_1(LoadingScene::loadingCallBack, this));
24 }
25 
26 void LoadingScene::loadingCallBack(Texture2D *texture){
27 
28     // 加载完成之后,切割图片,保存成精灵帧
29     AtlasLoader::getInstance()->loadAtlas("atlas.txt", texture);
30 
31     // 加载声音
32     SimpleAudioEngine::getInstance()->preloadEffect("sfx_die.ogg");
33     SimpleAudioEngine::getInstance()->preloadEffect("sfx_hit.ogg");
34     SimpleAudioEngine::getInstance()->preloadEffect("sfx_point.ogg");
35     SimpleAudioEngine::getInstance()->preloadEffect("sfx_swooshing.ogg");
36     SimpleAudioEngine::getInstance()->preloadEffect("sfx_wing.ogg");
37 
38     // 加载完成之后,跳转到欢迎场景
39     auto scene = WelcomeScene::create();
40     TransitionScene *transition = TransitionFade::create(1, scene);
41     Director::getInstance()->replaceScene(transition);
42 }

 

(三) WelcomeScene(欢迎场景)

  资源加载完成之后,跳转到欢迎场景,在这里我们将看到我们的主角---小鸟。

  ---> 显示背景

  ---> 地图无限滚动

  ---> 菜单

  ---> 小鸟类

WelcomeScene.h

 1 #pragma once
 2 #include "AtlasLoader.h"
 3 #include "WelcomeLayer.h"
 4 #include "BackgroundLayer.h"
 5 #include "cocos2d.h"
 6 using namespace cocos2d;
 7 using namespace std;
 8 
 9 /*
10     该类就非常简单了,主要在这里添加了一个WelcomeLayer层。
11 */
12 class WelcomeScene : public Scene{
13 public:
14     WelcomeScene(void);
15     ~WelcomeScene(void);
16     bool virtual init();
17     CREATE_FUNC(WelcomeScene);
18 };

WelcomeScene.cpp

 1 #include "WelcomeScene.h"
 2 
 3 WelcomeScene::WelcomeScene(){};
 4 
 5 WelcomeScene::~WelcomeScene(){};
 6 
 7 bool WelcomeScene::init(){
 8     bool bRet = false;
 9     do{
10         CC_BREAK_IF(!Scene::init());
11         auto _welcomeLayer = WelcomeLayer::create();
12         CC_BREAK_IF(!_welcomeLayer);
13         this->addChild(_welcomeLayer);
14         bRet = true;
15     }while(0);
16     return bRet;
17 }

 WelcomeLayer.h

 1 #pragma once
 2 
 3 #include "AtlasLoader.h"
 4 #include "SimpleAudioEngine.h"
 5 #include "CCMenuItem.h"
 6 #include "GameScene.h"
 7 #include "time.h"
 8 #include "cocos2d.h"
 9 #include "BirdSprite.h"
10 
11 using namespace cocos2d;
12 using namespace std;
13 using namespace CocosDenshion;
14 
15 const int START_BUTTON_TAG = 100;
16 
17 class WelcomeLayer : public Layer{
18 public:
19     WelcomeLayer(void);
20     ~WelcomeLayer(void);
21     virtual bool init();
22     
23     CREATE_FUNC(WelcomeLayer);
24     
25 private:
26     /**
27      * 开始按钮回调
28      */
29     void menuStartCallback(Object *sender);
30     
31     /**
32      * 地图无限滚动回调
33      */
34     void scrollLand(float dt);
35     
36     Sprite *land1;            // 地板1
37     Sprite *land2;            // 地板2
38     BirdSprite *bird;        // 主角小鸟
39 };

WelcomeLayer.cpp

  1 #include "WelcomeLayer.h"
  2 
  3 WelcomeLayer::WelcomeLayer(){};
  4 
  5 WelcomeLayer::~WelcomeLayer(){};
  6 
  7 bool WelcomeLayer::init(){
  8     if(!Layer::init()){
  9         return false;
 10     }
 11     
 12     Size visiableSize = Director::getInstance()->getVisibleSize();
 13     Point origin = Director::getInstance()->getVisibleOrigin();
 14 
 15     // 获取当前时间
 16     time_t t = time(NULL);
 17     tm* lt = localtime(&t);
 18     int hour = lt->tm_hour;
 19     
 20     // 根据当前时间创建背景(这里就用到了我们的AtlasLoader喽)
 21     Sprite *background;
 22     if(hour >= 6 && hour <= 17){
 23         background = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("bg_day"));
 24     }else{
 25         background = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("bg_night"));
 26     }
 27     background->setAnchorPoint(Point::ZERO);
 28     background->setPosition(Point::ZERO);
 29     this->addChild(background);
 30 
 31     // 游戏标题
 32     Sprite *title  = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("title"));
 33     title->setPosition(Point(origin.x + visiableSize.width/2 , (visiableSize.height * 5) / 7));
 34     this->addChild(title);
 35 
 36     // 添加开始菜单
 37     Sprite *startButton = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("button_play"));
 38     Sprite *activeStartButton = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("button_play"));
 39     
 40     // 创建菜单项 WelcomeLayer::menuStartCallback 为该菜单项的响应函数
 41     auto menuItem  = MenuItemSprite::create(startButton,activeStartButton,NULL,CC_CALLBACK_1(WelcomeLayer::menuStartCallback, this));
 42     menuItem->setPosition(Point(origin.x + visiableSize.width/2 ,origin.y + visiableSize.height*2/5));
 43 
 44     // 将菜单项加到菜单中,已NULL结束
 45     auto menu = Menu::create(menuItem,NULL);
 46     menu->setPosition(Point(origin.x ,origin.y));
 47     this->addChild(menu,1);
 48 
 49     // 创建小鸟(下面有具体的介绍)
 50     this->bird = BirdSprite::getInstance();
 51     this->bird->createBird();
 52     this->bird->setTag(BIRD_SPRITE_TAG);
 53     this->bird->setPosition(Point(origin.x + visiableSize.width / 2,origin.y + visiableSize.height*3/5 - 10));
 54     this->bird->idle();    // 使小鸟处于准备状态。
 55     this->addChild(this->bird);
 56 
 57     // 添加地板
 58     this->land1 = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("land"));
 59     this->land1->setAnchorPoint(Point::ZERO);
 60     this->land1->setPosition(Point::ZERO);
 61     this->addChild(this->land1);
 62 
 63     this->land2 = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("land"));
 64     this->land2->setAnchorPoint(Point::ZERO);
 65     this->land2->setPosition(this->land1->getContentSize().width - 2.0f, 0);
 66     this->addChild(this->land2);
 67 
 68     // 开启一个计时器,用于地板滚动
 69     this->schedule(schedule_selector(WelcomeLayer::scrollLand), 0.01f);
 70 
 71     // 版权
 72     Sprite *copyright = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("brand_copyright"));
 73     copyright->setPosition(Point(origin.x + visiableSize.width/2, origin.y + visiableSize.height/6));
 74     this->addChild(copyright, 10);
 75 
 76     return true;
 77 }
 78 
 79 void WelcomeLayer::scrollLand(float dt){
 80     /*  地图无限滚动原理:
 81         实际上是有两块地图并排放置,每隔一段时间设置两块地图的X坐标,当第一块地图完全移出屏幕的时候,
 82         第二块地图正好完全显示在屏幕内,这时再将第一块的地图X坐标设置为0,第二块地图X坐标设置为第一块地图的后面,
 83         无限循环,就形成了地图无限滚动的视觉效果。
 84     */
 85         
 86     this->land1->setPositionX(this->land1->getPositionX() - 2.0f);
 87     this->land2->setPositionX(this->land1->getPositionX() + this->land1->getContentSize().width - 2.0f);
 88 
 89     if(this->land2->getPositionX() == 0) {
 90         this->land1->setPositionX(0);
 91     }
 92 }
 93 
 94 void WelcomeLayer::menuStartCallback(Object *sender){
 95     // 播放音效
 96     SimpleAudioEngine::getInstance()->playEffect("sfx_swooshing.ogg");
 97     // 移除小鸟
 98     this->removeChildByTag(BIRD_SPRITE_TAG);
 99     // 跳转到游戏场景
100     auto scene = GameScene::create();
101     TransitionScene *transition = TransitionFade::create(1, scene);
102     Director::getInstance()->replaceScene(transition);
103 }

 小鸟:

BirdSprite.h

 1 #pragma once
 2 #include "cocos2d.h"
 3 #include "AtlasLoader.h"
 4 
 5 using namespace cocos2d;
 6 
 7 // 小鸟的三种状态
 8 typedef enum{
 9     ACTION_STATE_IDLE,            // 准备
10     ACTION_STATE_FLY,            // 飞行
11     ACTION_STATE_DIE            // 死亡
12 } ActionState;
13 
14 const int BIRD_SPRITE_TAG = 10003;
15 
16 class BirdSprite : public Sprite {
17 public:
18     /**
19     * 默认构造
20     */
21     BirdSprite();
22 
23     /**
24     * 默认析构
25     */
26     ~BirdSprite();
27 
28     /**
29      * 获取单例
30      */
31     static BirdSprite* getInstance();
32 
33     /**
34     * 初始化
35     */
36     bool virtual init();
37 
38     /**
39      * 创建小鸟
40      */
41     bool createBird();
42 
43     //CREATE_FUNC(BirdSprite);
44 
45     /**
46     * 使小鸟处于准备状态
47     */
48     void idle();
49 
50     /**
51     * 使小鸟处于飞行状态
52     */
53     void fly();
54 
55     /**
56     * 使小鸟处于死亡状态
57     */
58     void die();
59     
60 protected:
61     /**
62     * 创建小鸟动画
63     * fmt 格式化字符串
64     * count 帧数
65     * fps 指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数
66     */
67     static cocos2d::Animation *createAnimation(const char *fmt, int count, float fps);
68 
69     /**
70      * 随机创建小鸟
71      */
72     void createBirdByRandom();
73 
74 private:
75     static BirdSprite* shareBirdSprite;
76 
77     /**
78     * 切换状态
79     */
80     bool changeState(ActionState state);
81 
82     // 小鸟动作
83     Action* idleAction;
84     Action* swingAction;
85 
86     // 当前状态
87     ActionState currentStatus;
88 
89     // 小鸟的名字,用于随机创建小鸟
90     string birdName;
91 
92     // 小鸟名字格式化字符,用于创建小鸟动画
93     string birdNameFormat;
94 
95     // 记录第一次进入游戏.
96     unsigned int isFirstTime;
97 };

BirdSprite.cpp

  1 #include "BirdSprite.h"
  2 
  3 BirdSprite::BirdSprite() {
  4 }
  5 
  6 BirdSprite::~BirdSprite() {
  7 }
  8 
  9 BirdSprite* BirdSprite::shareBirdSprite = nullptr;
 10 BirdSprite* BirdSprite::getInstance(){
 11     if(shareBirdSprite == NULL){
 12         shareBirdSprite = new BirdSprite();
 13         if(!shareBirdSprite->init()){
 14             delete(shareBirdSprite);
 15             shareBirdSprite = NULL;
 16             CCLOG("ERROR: Could not init shareBirdSprite");
 17         }
 18     }
 19     return shareBirdSprite;
 20 }
 21 
 22 bool BirdSprite::init() {
     if(!Sprite::init())     {        return false;     } 23     this->isFirstTime = 3;
 24     return true;
 25 }
 26 
 27 bool BirdSprite::createBird(){
 28     // 随机获得一种小鸟的名字
 29     this->createBirdByRandom();
 30     if(Sprite::initWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName(this->birdName))) {
 31         
 32         // 创建动画
 33         Animation* animation = this->createAnimation(this->birdNameFormat.c_str(), 3, 10);
 34         // 用动画播放器包装动画(实际也是一种动作)
 35         Animate* animate = Animate::create(animation);
 36         // 准备动作等于一个不知道累无限煽动小膀的鸟
 37         this->idleAction = RepeatForever::create(animate);
 38 
 39         // 小鸟上下移动的动作
 40         ActionInterval *up = CCMoveBy::create(0.4f,Point(0, 8));
 41         ActionInterval *upBack= up->reverse();
 42         this->swingAction = RepeatForever::create(Sequence::create(up, upBack, NULL));
 43         return true;
 44     }else {
 45         return false;
 46     }
 47 }
 48 
 49 void BirdSprite::idle() {
 50     if (changeState(ACTION_STATE_IDLE)) {
 51         this->runAction(idleAction);
 52         this->runAction(swingAction);
 53     }
 54 }
 55 
 56 void BirdSprite::fly() {
 57     if(changeState(ACTION_STATE_FLY)) {
 58         this->stopAction(swingAction);
 59 
 60         // 设置受重力反映(物理引擎,下面详细介绍)
 61         this->getPhysicsBody()->setGravityEnable(true);
 62     }
 63 }
 64 
 65 void BirdSprite::die() {
 66     if(changeState(ACTION_STATE_DIE)) {
 67         // 死亡就是停止所有动作
 68         this->stopAllActions();
 69     }
 70 }
 71 
 72 Animation* BirdSprite::createAnimation(const char *fmt, int count, float fps) {
 73     // 创建动画(向Animation中添加精灵帧)
 74     Animation *animation = Animation::create();
 75     animation->setDelayPerUnit(1/fps);
 76     for (int i = 0; i < count; i++){
 77         const char *filename = String::createWithFormat(fmt, i)->getCString();
 78         SpriteFrame *frame = AtlasLoader::getInstance()->getSpriteFrameByName(filename);
 79         animation->addSpriteFrame(frame);
 80     }
 81     return animation;
 82 }
 83 
 84 bool BirdSprite::changeState(ActionState state) {
 85     //this->stopAllActions();
 86     currentStatus = state;
 87     return true;
 88 }
 89 
 90 void BirdSprite::createBirdByRandom(){
 91     if(this->isFirstTime & 1){
 92         this->isFirstTime &= 2;
 93     }else if(this->isFirstTime & 2){
 94         this->isFirstTime &= 1;
 95         return ;
 96     }
 97 
 98     // 随机一个数,用于创建小鸟
 99     srand((unsigned)time(NULL));
100     int type = ((int)rand())% 3;
101     switch (type)
102     {
103     case 0:
104         this->birdName = "bird0_0";
105         this->birdNameFormat = "bird0_%d";
106         break;
107     case 1:
108         this->birdName = "bird1_0";
109         this->birdNameFormat = "bird1_%d";
110         break;
111     case 2:
112         this->birdName = "bird2_0";
113         this->birdNameFormat = "bird2_%d";
114         break;
115     default:
116         this->birdName = "bird2_0";
117         this->birdNameFormat = "bird2_%d";
118         break;
119     }
120 }

 

(四)物理引擎:http://www.cnblogs.com/LeavesSmallAnt/p/4496420.html

(五)GameScene(游戏场景)

  上面欢迎界面完成了之后,点击开始按钮该进入到游戏的主要部分了---游戏场景。

  游戏场景主要分为四个游戏层:

    背景层:主要是游戏背景的显示

    游戏层:小鸟+水管

    状态层:游戏过程中分数的显示,根据游戏的不同阶段,显示游戏状态(开始、游戏进行中、游戏结束)

    操作层:游戏触摸层,用于响应触摸事件

GameScene.h

 1 #pragma once
 2 #include "cocos2d.h"
 3 #include "BackgroundLayer.h"
 4 #include "GameLayer.h"
 5 #include "StatusLayer.h"
 6 #include "OptionLayer.h"
 7 
 8 using namespace cocos2d;
 9 
10 /*
11     游戏场景:背景层/游戏层/状态层/操作层
12 */
13 class GameScene:public Scene{
14 public:
15     GameScene();
16 
17     ~GameScene();
18 
19     bool virtual init();
20     
21     // 重置游戏
22     void restart();
23 
24     CREATE_FUNC(GameScene);
25 };

GameScene.cpp

 1 #include "GameScene.h"
 2 
 3 GameScene::GameScene(){}
 4 
 5 GameScene::~GameScene(){}
 6 
 7 bool GameScene::init(){
 8     // 创建物理世界
 9     // 相当于 auto scene = Scene::createWithPhysics()
10     if(Scene::initWithPhysics()){
11         // 开启调试模式 调试模式可以将模拟的物理状态都绘制出来
12         //this->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
13 
14         // 设置物理世界重力, Y轴向下加速度900
15         this->getPhysicsWorld()->setGravity(Vect(0, -900));
16 
17         // 添加背景层
18         auto backgroundLayer = BackgroundLayer::create();
19         if(backgroundLayer) {
20             this->addChild(backgroundLayer);
21         }
22 
23         // 状态层
24         auto statusLayer = StatusLayer::create();
25 
26         // 游戏层
27         auto gameLayer = GameLayer::create();
28         if(gameLayer) {
29             gameLayer->setPhyWorld(this->getPhysicsWorld());    // 设置物理世界
30             gameLayer->setDelegator(statusLayer);                // 设置委托,在statusLayer委托gameLayer更新状态
31             this->addChild(gameLayer);
32         }
33 
34         // 状态层
35         if(statusLayer) {
36             this->addChild(statusLayer);
37         }
38 
39         // 操作层
40         auto optionLayer = OptionLayer::create();
41         if(optionLayer) {
42             optionLayer->setDelegator(gameLayer);
43             this->addChild(optionLayer);
44         }
45         return true;
46     }else {
47         return false;
48     }
49 }
50 
51 void GameScene::restart() {
52     this->removeAllChildrenWithCleanup(true);
53     this->init();
54 }

然后逐层介绍

BackgroundLayer.h

 1 #pragma once
 2 #include "cocos2d.h"
 3 #include "AtlasLoader.h"
 4 #include "time.h"
 5 using namespace cocos2d;
 6 using namespace std;
 7 /*
 8     背景层相对简单,在init方法中根据时间添加一张背景,OK了
 9 */
10 class BackgroundLayer:public Layer{
11 public:
12     BackgroundLayer(void);
13     
14     ~BackgroundLayer(void);
15     
16     virtual bool init();
17     
18     CREATE_FUNC(BackgroundLayer);
19     
20     // 获得地板的高度
21     static float getLandHeight();
22 };

BackgroundLayer.cpp

 1 #include "BackgroundLayer.h"
 2 BackgroundLayer::BackgroundLayer(){};
 3 BackgroundLayer::~BackgroundLayer(){};
 4 
 5 bool BackgroundLayer::init(){
 6     if(!Layer::init()){
 7         return false;
 8     }
 9     
10     // 根据时间添加背景
11     time_t t = time(NULL);
12     tm* lt = localtime(&t);
13     int hour = lt->tm_hour;
14     Sprite *background;
15     if(hour >= 6 && hour <= 17){
16          background = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("bg_day"));
17     }else{
18         background = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("bg_night"));
19     }
20     background->setAnchorPoint(Point::ZERO);
21     background->setPosition(Point::ZERO);
22     this->addChild(background);
23 
24     return true;
25 }
26 
27 float BackgroundLayer::getLandHeight() {
28     return Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrameByName("land"))->getContentSize().height;
29 }

GameLayer中涉及到一个委托模式(代理模式)

 http://www.cnblogs.com/LeavesSmallAnt/p/4505254.html

这个程序中用到的是动态代理,动态代理指在实现阶段不用关心代理谁,而在运行阶段才指定代理哪个对象。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!