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

原文地址:https://www.cnblogs.com/gcczhongduan/p/5135509.html