首页 > 代码库 > Cocos2d 游戏状态机
Cocos2d 游戏状态机
加cocos2d 是标题党。其实跟cocos2d无关。
1.游戏背景介绍
比如有这么一个"记忆"类的比赛游戏。你和电脑对战,轮到谁的回合,谁翻两张牌,如果两张牌一样,就消掉这两张牌,得2分,可以继续翻牌,如果两张牌不一样,就换一个人。直到最后,看谁的得分高。
先把图画出来会清晰些:
2.先看下不好的设计方式
我们来设计游戏大致架构,用一个圈表示一个状态。
typedef enum{ WaitingPlayer, CheckPlayer, AIThink, AIFirstCard, AISecondCard, CheckAI }MatchGameState;
准备一个_state的变量来记录当前的状态,然后放到update函数里,执行下面的伪代码。
void MatchLayer::update(float dt){ if(allCards.size() == 0){ _state = GameOver; } switch(_state){ case WaitingPlayer: if(cardCount == 2){ _state = CheckPlayer; cardCount = 0; } break; case CheckPlayer: if(playerCard1 == playerCard2){ 玩家得分 _state = WaitingPlayer; }else{ _state = AIThink; 把玩家点开的卡加入到记忆数组中 } break; case AIThink: 从记忆的数组中找两张相同的,找不到就随机准备两种卡 _state = AIFirstCard; break; case AIFirstCard: 点开第一张卡 如果之前没找到相同卡,把这卡加入到记忆数组 _state = AISecondCard; break; case AISecondCard: 从记忆的数组中找两张相同的: 如果找到跟第一张一样,就点开它,找不到就点刚开始的随机第2张,并且把第2张加入到记忆数组中。 _state = CheckAI; break; case CheckAI: if(AICard1 == AICard2){ _state = AIThink; 电脑得分 }else{ _state = WaitingPlayer; } } }
这样写是可以,但是随着代码行数增加和业务逻辑变得复杂,后续会比较难维护。
3.使用"设计模式"来重构
我们来看下如何重构,使用"设计模式"来重构它。我盗了一张图来说明。
不知道这方法是设计模式中的哪种。
我们打算把所有的状态都用一个类来实现,它们都继承一个基类叫MatchState,它非常简单。有一个类来管理所有的状态。 MatchState如下:
#ifndef _MATCHSTATE_ #define _MATCHSTATE_ class MatchState{ public: virtual void Update() = 0; }; #endif
我这里就没加OnEnter和OnExit了。简单起见。
为了简单些,就把Layer作为状态管理类,在Layer中增加一个属性,来表示当前状态:
MatchState* currentState;
在主要的Layer中增加一个方法来切换当前状态:
void changeState(MatchState* state){ delete currentState; currentState = state; }
在update中就简单了,一直执行当前状态的Update方法:
void MatchLayer::update(float dt){ if(allCards.size() == 0){ _state = GameOver; } currentState->Update(); }
每个状态的具体业务逻辑都写在自己的类中。比如WaitingPlayerState类:
#ifndef _WAITINGPLAYERSTATE_H #define _WAITINGPLAYERSTATE_H #include "MatchState.h" class WaitingPlayerState : public MatchState{ public: WaitingPlayerState(){ } void Update(){ if(sGlobal->cardCount == 2){ sGlobal->matchLayer->changeState(new CheckPlayerCardsState()); } } }; #endif
这里sGlobal是一个单例。
再比如CheckPlayerCardsState:
#ifndef _CHECKPLAYERCARDSSTATE_H #define _CHECKPLAYERCARDSSTATE_H #include "MatchState.h" class CheckPlayerCardsState : public MatchState { public: void Update(){ //非常复杂的具体业务逻辑写在这里 if(playerCard1 == playerCard2){ 玩家得分 sGlobal->matchLayer->changeState(new WaitingPlayerState ()); }else{ sGlobal->matchLayer->changeState(new AIThinkState ()); 把玩家点开的卡加入到记忆数组中 } } }; #endif
其他状态类就不写出来了,总之通过这样把一个状态用一个类来表示,大大的使代码简洁些,扩展性强些。
http://www.waitingfy.com/archives/1273
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。