博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cocos2dx3.3开发FlappyBird总结十二:状态层设计
阅读量:5817 次
发布时间:2019-06-18

本文共 5892 字,大约阅读时间需要 19 分钟。

状态层是比较复杂的了,状态层需要与游戏层通信,因此也需要为游戏层先设计一个代理类,以便状态层遵守游戏层的代理,这样游戏层就可以在游戏开始、得分、结束时,告诉状态层做出相应的状态表现了。

游戏层的代理类:

/** * The delegate between status layer and game layer */class GameStatusDelegate {
public: /** * When the game start, this method will be called */ virtual void onGameStart() = 0; /** * During paying, after the score changed, this method will be called * * @param score The latest score */ virtual void onGamePlaying(int score) = 0; /** * When game is over, this method will be called * * @param currentScore Current game score * @param historyBestScore The best score in the history of the player */ virtual void onGameEnd(int currentScore, int historyBestScore) = 0;};

只有三个方法,分别对应游戏开始、玩家得分、游戏结束。

那么状态层需要遵守代理:

/** *The status layer,showing the status information * in the game. */class StatusLayer : public cocos2d::Layer, public GameStatusDelegate

遵守代理后,必须声明代理中的方法:

/**   * Override from GameStatusDelegate   *   * @see GameStatusDelegate declaration.   */  void onGameStart(void);  void onGamePlaying(int score);  void onGameEnd(int currentScore, int historyBestScore);

如果不声明,会编译不通过的,这是必须实现的。

这个层中,有四种精灵需要控制:

cocos2d::Sprite *_getReadySprite;  cocos2d::Sprite *_tutorialSprite;  cocos2d::Node *_scoreNode;  cocos2d::Sprite *_blinkSprite;

分别对应GetReady、指导图、得分、闪屏图

在初始化时,先邓加载0~9数字精灵:

bool StatusLayer::init() {  if (!Layer::init()) {    return false;  }  // preload number sprite frames to memory  ScoreNumber::getInstance()->loadNumber(kScoreNumberFont.c_str(), "font_0%02d", 48);  ScoreNumber::getInstance()->loadNumber(kScoreNumberScore.c_str(), "number_score_%02d", 0);  // At the first time, the game is ready to play  this->showGameStatus(kGameStateReady);  return true;}

关于数字特效类ScoreNumber,后面再单独说明。

这个类中最重要的显示状态方法:

void StatusLayer::showGameStatus(GameState status, int currentScore, int historyBestScore) {  auto size = Director::getInstance()->getVisibleSize();  auto origin = Director::getInstance()->getVisibleOrigin();  switch (status) {    case kGameStateReady: {      const char *scoreName = kScoreNumberFont.c_str();      _scoreNode = ScoreNumber::getInstance()->convert(scoreName, currentScore);      _scoreNode->setPosition(origin.x + size.width / 2, origin.y + size.height * 5 / 6);      this->addChild(_scoreNode);      _getReadySprite = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("text_ready"));      _getReadySprite->setPosition(origin.x + size.width / 2, origin.y + size.height * 2 / 3);      this->addChild(_getReadySprite);      _tutorialSprite = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("tutorial"));      _tutorialSprite->setPosition(origin.x + size.width / 2, origin.y + size.height * 1 / 2);      this->addChild(_tutorialSprite);    }      break;    case kGameStateStarted: {      _getReadySprite->runAction(FadeOut::create(0.4f));      _tutorialSprite->runAction(FadeOut::create(0.4f));    }      break;    case kGameStateOver: {      _currentScore = currentScore;      _bestScore = historyBestScore;      if (_currentScore > _bestScore) {        _bestScore = _currentScore;        _isNewRecord = true;      } else {        _isNewRecord = false;      }      this->removeChild(_scoreNode);      // Game over      auto overSprite = Sprite::createWithSpriteFrame(AtlasLoader::getInstance()->getSpriteFrame("text_game_over"));      auto size = Director::getInstance()->getVisibleSize();      auto origin = Director::getInstance()->getVisibleOrigin();      overSprite->setPosition(origin.x + size.width / 2, origin.y + size.height * 2 / 3);      this->addChild(overSprite);      // Add animation      auto fadein = FadeIn::create(0.5f);      auto actionDone = CallFunc::create(std::bind(&StatusLayer::showScorePanel, this));      auto sequence = Sequence::createWithTwoActions(fadein, actionDone);      overSprite->stopAllActions();      overSprite->runAction(sequence);    }      break;    default:      break;  }}

如果状态为ready,即准备状态,

准备状态图:
准备状态图

状态为kGameStateStarted,表示开始游戏时,

_getReadySprite->runAction(FadeOut::create(0.4f));
_tutorialSprite->runAction(FadeOut::create(0.4f));
只是添加淡出效果

状态为游戏结束时,显示游戏结束:

这里写图片描述

当游戏结束的时候,显示Game Over 精灵,然后添加淡入淡出的动画,来显示得分结果显示面板和重玩、机会按钮,

不过这里并没有实现机会使用按钮,因此此功能就留给喜欢研究扩展的朋友吧。

刷新得分面板用户得分函数,从0到玩家得分,有一个动画的过程,

void StatusLayer::refreshScoreUpdate(float delta) {  const int kCurrentSpriteTag = 100;  if (this->getChildByTag(kCurrentSpriteTag)) {    this->removeChildByTag(kCurrentSpriteTag);  }  const char *score = kScoreNumberScore.c_str();  _scoreNode = ScoreNumber::getInstance()->convert(score, _tmpScore, kGravityDirectionRight);  _scoreNode->setAnchorPoint(Vec2(1, 0));  auto size = Director::getInstance()->getVisibleSize();  auto origin = Director::getInstance()->getVisibleOrigin();  _scoreNode->setPosition(origin.x + size.width * 3 / 4 + 4, origin.y + (size.height - _scoreNode->getContentSize().height) / 2 + 7);  this->addChild(_scoreNode);  ++_tmpScore;  if (_tmpScore > _currentScore) {    unschedule(schedule_selector(StatusLayer::refreshScoreUpdate));  }}

这是通过定时器来回调的,当刷新完成时,需要取消掉定时器。

点击重玩按钮时,进入到此函数:

void StatusLayer::menuRestartCallback(cocos2d::Ref *pSender) {  CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("sfx_swooshing.ogg");  // We can't add TransitionScene object, otherwise it can't receive any touch event.  // I don't know why.  // We should remove all children and clean up resources, otherwise it will crash at  // some time in the future. In fact, I don't know why, when Director replace a new  // scene, does it remove and clean up?  auto scene = Director::getInstance()->getRunningScene();  scene->removeAllChildrenWithCleanup(true);  Director::getInstance()->replaceScene(GameScene::createScene());}

如果不加上这两行代码先释放资源,时不时就会崩溃,不知道是不是因为是自动释放的,但是事件循环并没有到,因此一直没有得到释放而导致的。

auto scene = Director::getInstance()->getRunningScene();  scene->removeAllChildrenWithCleanup(true);

这两行代码只是先把当前场景的所有资源先释放掉。

下一步,看一看我们设计的数字特效类

你可能感兴趣的文章
Linux 目录结构及内容详解
查看>>
Oracle命令导入dmp文件
查看>>
OCP读书笔记(24) - 题库(ExamD)
查看>>
解决Unable to load R3 module ...VBoxDD.dll (VBoxDD):GetLastError=1790
查看>>
.net excel利用NPOI导入oracle
查看>>
第六课:数据库的基本工具
查看>>
$_SERVER['SCRIPT_FLENAME']与__FILE__
查看>>
skynet实践(8)-接入websocket
查看>>
系统版本判断
查看>>
My97DatePicker 日历插件
查看>>
0603 学术诚信与职业道德
查看>>
小点心家族第3位成员——楼层定位效果
查看>>
Knockout.Js官网学习(enable绑定、disable绑定)
查看>>
hive基本操作与应用
查看>>
excel快捷键设置
查看>>
poj3692
查看>>
python之信号量【Semaphore】
查看>>
html5纲要,细谈HTML 5新增的元素
查看>>
Android应用集成支付宝接口的简化
查看>>
[分享]Ubuntu12.04安装基础教程(图文)
查看>>