State模式之卡通农场(HayDay)

supercell最近处的卡通农场也叫HayDay异常火爆,这里我也来写一下游戏的主要框架。

此游戏的核心较为简单,就是一个状态机在不停的运作,这里考虑使用状态模式来实现,为什么要选择状态机呢,因为游戏中的绝大多数的角色都是状态在改变行为,所以使用状态机是在合适不过了。

首先分析一下游戏中的元素,要做到分类准确,大致如下图

 

  diable building free baking mature hungry gain  
圈养类/放养类                
植物                
鱼类                
机器类(虾,机器,矿石,火车站)                
消费者(卡车,购买者)                
装饰类(石头,宝箱,装饰树,其他装饰物,地摊)                
果实类                

可能不同的设计者在分类的出发点不同,我是从状态的个数和种类上分类的。

 

using UnityEngine;
using System.Collections;

public abstract class AbsState 
{
    //当前状态的名字
    public string strStateName_;
    //当前状态对应的模型
    public GameObject curStateModel_;
    //当前状态对应的动画片段
    public AnimationClip curStateClip_;
    //状态持续时间
    public long lDuration_;
    //切换状态
    public abstract void SwitchState(Unit unit); 
}
using UnityEngine;
using System.Collections;

//单位对应的时期。比如树 有第一代,第二代,第三代,第四代(第四代是被好友拯救的一代)
public enum EnAge
{
    EN_AGE_1,
    EN_AGE_2,
    EN_AGE_3,
    EN_AGE_4,
}

//参与状态机的单位
public abstract class Unit 
{
    //当前的状态
    public AbsState curState_;
    //多任务的单位示范完成所有的任务,比如机器可能有多个格子在生产东西,那么必须等到所有的格子都完成了任务才会去切换状态
    public bool bFinishTask_;
    //单位所在的位置
    public Vector2 position_;
    //单位所在的时代
    public EnAge age_;
}

以上是主要的抽象体,一个是负责状态的,一个是辅助单位的 这里也符合了状态模式的设计要求,Unit里面有了对虚拟状态的关联

接下来就是对各个具体的单位和状态进行处理了

 

using UnityEngine;
using System.Collections;

public class CAnimal : Unit
{

}
/// <summary>
/// Disable state.
/// 未被激活状态
/// </summary>
using UnityEngine;
using System.Collections;

public class DisableState : AbsState
{
    public override void SwitchState (Unit unit)
    {
        if(unit is CMachine)
        {
            Debug.Log("DisableState -> BuildingState");
            unit.curState_ = new BuildingState();
        }
        else
        {
            Debug.Log("DisableState -> FreeState");
            unit.curState_ = new FreeState();
        }    
    }
}

 

using UnityEngine;
using System.Collections;

public class FreeState : AbsState
{
    public override void SwitchState (Unit unit)
    {
        if(unit is CMachine)
        {
            Debug.Log("free -> BakingState");
            unit.curState_ = new BakingState();
        }
        else if(unit is CProduct)
        {
            unit.curState_ = new GainState();
            Debug.Log("free-> GainState");
        }
        else
        {
            Debug.Log("free -> matrue");
            unit.curState_ = new MatureState();
        }
    }
}

此处省略了所有状态和所有具体单位的代码,都类似的。

最后客户端调用

using UnityEngine;
using System.Collections;

public class Client : MonoBehaviour {
    Unit unit;
    // Use this for initialization
    void Start () {
        //初始化一个动物
        unit = new CAnimal();
        //动物的初始状体是不被激活的
        unit.curState_ = new DisableState();    
    }
    
    // Update is called once per frame
    void Update () {
      //测试:抬起space键进行状态切换
      //游戏中大部分是通过倒计时的方式进行切换,这不进行说明每种切换的方式,点到为止
      if(Input.GetKeyUp(KeyCode.Space))
        {
            unit.curState_.SwitchState(unit);
        }
    }
}

 

欢迎拍砖

 

posted @ 2014-07-29 16:07  p_towin  阅读(599)  评论(0编辑  收藏  举报