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
这个程序中用到的是动态代理,动态代理指在实现阶段不用关心代理谁,而在运行阶段才指定代理哪个对象。
来源:https://www.cnblogs.com/LeavesSmallAnt/p/4499482.html