加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,它很easy。
有一个类来管理全部的状态。
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