zoukankan      html  css  js  c++  java
  • 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,它很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

  • 相关阅读:
    js中的原生Ajax和JQuery中的Ajax
    this的用法
    static的特性
    时政20180807
    java compiler没有1.8怎么办
    Description Resource Path Location Type Java compiler level does not match the version of the installed Java project facet Unknown Faceted Project Problem (Java Version Mismatch)
    分词器
    [数算]有一个工程甲、乙、丙单独做,分别要48天、72天、96天完成
    一点感想
    解析Excel文件 Apache POI框架使用
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5135509.html
Copyright © 2011-2022 走看看