星空网 > 软件开发 > ASP.net

Game中的状态机

我相信大多数博友都会玩游戏。

玩游戏,牵涉到状态包含 登陆,正常,死亡,复活,下线,

在上面状态的基础上。同时包含 站立,走动,跑动,不可移动施法状态,

              战斗状态,

通常这是三个不同的分组。也就说可以同时存在的状态和不可同时存在的状态。

通常情况下也许你会这么定义,

//分组1public bool 登陆 = false;public bool 死亡 = false;public bool 复活 = false;public bool 下线 = false;public bool 正常 = false;public bool 打坐 = false;//分组2public bool 站立 = false;public bool 走动 = false;public bool 跑动 = false;public bool 施法 = false;//分组3public bool 战斗 = false;

这种情况下,判断就变得很复杂,因为存在,同时成立和非同时成立的状态,

例如,战斗的同时可以走动,也可以跑动,或者技能施法

但是在打坐,下线,死亡等状态的时候既不能走动,也不能战斗也不能施法。

这样一来一去,判断的if else 会多的,让你头痛欲裂的吧。

或许你会想到,是要枚举,因为枚举提供位运算,提供Enum.HasFlag()方法来判断是否存在值

public enum Stauts{  //分组1  空值,  登陆,  死亡,  复活,  下线,  正常,  打坐,  //分组2  站立,  走动,  跑动,  施法,  //分组3  战斗,}

查看一下使用方式

Stauts sValue = Stauts.登陆;sValue = sValue | Stauts.站立;if (sValue.HasFlag(Stauts.站立)){  Console.WriteLine("存在站立状态");}

输出:Game中的状态机

 

但是,继续测试一下

Game中的状态机

 

这样看出来了,我并没有设置复活状态,但是却存在复活状态~!

探究得明原因,是因为 位或(|) 运算,  按位或(|)表示相对应的每位至少有一个为1,则结果为1,只有两个都为0,结果才为0.

所以,我们应该设置枚举值的不同值;

为了更直观的查看运算方式,我们输出枚举值的二进制值,

public static void Show(Stauts value){  string log = ("结果:" + ((long)value).ToString().PadLeft(10, ' ') + " -> " + Convert.ToString(((long)value), 2).PadLeft(64, '0'));  Console.WriteLine(log);}

 

查看一下Game中的状态机

我们看到

Stauts.登陆 | Stauts.死亡 位或计算方式,结果值。

这些明白了,那就是枚举的值,定义不合法,

public enum Stauts{  //分组1  空值 = 0,  登陆 = 1,  死亡 = 2,  复活 = 4,  下线 = 8,  正常 = 10,  打坐 = 20,  //分组2  站立 = 40,  走动 = 80,  跑动 = 100,  施法 = 200,  //分组3  战斗 = 400,}

 

 

输出结果

Game中的状态机

这下,没有了复活状态。这样判断,会减少一半,

可还是出现一个问题。那就是分组问题,也就说,死亡状态和复活状态不能同时存在,

死亡状态和跑动状态也不可能同时存在

那么我们在想,枚举值的能不能分组呢?

Game中的状态机

可惜C#下面枚举值,只能使用整型的基础类型。

没办法只能另辟蹊径:

  public class EnumStatus  {    public long Value { get; private set; }    public long GroupValue { private set; get; }    public EnumStatus(long value, long group)    {      this.Value = value;    }  }

接下来我们设置一组常量

    // 0x000000一旦竟然这组状态忽略一切状态    public static EnumStatus Status0_空值 = new EnumStatus(0, 0x000000);    public static EnumStatus Status0_登陆 = new EnumStatus(1 << 0, 0x000000);    public static EnumStatus Status0_死亡 = new EnumStatus(1 << 1, 0x000000);    public static EnumStatus Status0_复活 = new EnumStatus(1 << 2, 0x000000);    public static EnumStatus Status0_下线 = new EnumStatus(1 << 3, 0x000000);    public static EnumStatus Status0_正常 = new EnumStatus(1 << 4, 0x000000);    public static EnumStatus Status1_打坐 = new EnumStatus(1 << 5, 0x000000);    //移动组状态 4个状态值    public static EnumStatus Status1_站立 = new EnumStatus(1 << 6, 0x00000f);//4位一组    public static EnumStatus Status1_走动 = new EnumStatus(1 << 7, 0x00000f);//    public static EnumStatus Status1_跑动 = new EnumStatus(1 << 8, 0x00000f);//    public static EnumStatus Status1_施法 = new EnumStatus(1 << 9, 0x00000f);// 无法移动的施法    //战斗状态 这组只有一个状态值    public static EnumStatus Status2_战斗 = new EnumStatus(1 << 10, 0x000010);//

后面的分组值,的由来是

Game中的状态机Game中的状态机

0x00000f  二进制 0000,1111,

0x000010 二进制 0001,0000,
这样就成功分组了

也许看到这里你需要一定的位运算知识了;

接下来我在介绍一下

位运算的操作符

//// 按位异或(^)比较特殊,它比较的是如果两个不同则值为1(如:(1、0)(0、1)),相同则为0(如:(1、1)(0、0))。//// 按位与(&)表示相对应的两位必须都为1,结果才为1,否则为0//// 按位或(|)表示相对应的每位至少有一个为1,则结果为1,只有两个都为0,结果才为0.//// 按位取反~ 运算符对操作数执行按位求补运算,其效果相当于反转每一位。

修改一下计算值

  public class EnumStatus  {    public long Value { get; private set; }    public long GroupValue { private set; get; }    public EnumStatus(long value, long group)    {      this.Value = value;    }    public bool HasFlag(EnumStatus status)    {      return (this.Value & status.Value) != 0;    }    public void Show()    {      string log = ("结果:" + this.Value.ToString().PadLeft(10, ' ') + " -> " + Convert.ToString(this.Value, 2).PadLeft(64, '0'));      Console.WriteLine(log);    }    public static EnumStatus operator |(EnumStatus statusLeft, EnumStatus statusRight)    {      statusLeft.Value = statusLeft.Value & statusRight.GroupValue | statusRight.Value;      return statusLeft;    }    public static EnumStatus operator &(EnumStatus statusLeft, EnumStatus statusRight)    {      statusLeft.Value = statusLeft.Value & (~statusRight.Value);      return statusLeft;    }  }

 

这下是不是很轻松的解决了这一系列的状态问题呢?包括各种同时存在和不同时的存在的状态~!

但是这也有一个弊端,那就是值只有64个,也就是64个状态,,虽然存在分组。但是每一个分组的值都必须不同才行。

不知道,各位看官还有么没有更好的办法????

==============================================================================================

java版本的

 

java的枚举是可以自定义的这方面比较方便

但是java没有运算符重载,

enum EnumStatus {  //0x000000一旦竟然这组状态忽略一切状态  Status0_空值(0, 0x000000),  Status0_登陆(1 << 0, 0x000000),  Status0_下线(1 << 1, 0x000000),  Status0_正常(1 << 2, 0x000000),  //移动组状态  Status1_走动(1 << 3, 0x00000f),  Status1_跑动(1 << 4, 0x00000f);  Long value = 0L;  Long group = 0L;  private EnumStatus(long value, long group) {    this.value = value;    this.group = group;  }  public boolean hasFlag(EnumStatus status) {    return (value & (~status.value)) != 0;  }  public void addStatus(EnumStatus status) {    value = value & status.group | status.value;  }  public void removeStatus(EnumStatus status) {    value = value & (~status.value);  }  public void show() {    String log = "结果:" + padLeft(this.value + "", 10, " ") + " -> " + padLeft(Long.toBinaryString(this.value), 64, "0");    System.out.println(log);  }  String padLeft(String source, int length, String paddingChar) {    String strB = Long.toBinaryString(this.value);    int forCount = length - strB.length();    for (int i = 0; i < forCount; i++) {      strB = paddingChar + strB;    }    return strB;  }}

测试代码

    EnumStatus status = EnumStatus.Status0_空值;    System.out.println("===============Status.Status0_空值================");    status.show();    System.out.println("===============Status.Status0_登陆================");    status.addStatus(EnumStatus.Status0_登陆);    status.show();    if (status.hasFlag(EnumStatus.Status0_登陆)) {      System.out.println("存在状态 Status.Status0_登陆");    } else {      System.out.println("不存在状态 Status.Status0_登陆");    }    System.out.println("===============Status.Status0_正常================");    status.addStatus(EnumStatus.Status0_正常);    status.show();    if (status.hasFlag(EnumStatus.Status0_登陆)) {      System.out.println("存在状态 Status.Status0_登陆");    } else {      System.out.println("不存在状态 Status.Status0_登陆");    }    System.out.println("===============Status.Status1_跑动================");    status.addStatus(EnumStatus.Status1_跑动);    status.show();    if (status.hasFlag(EnumStatus.Status0_正常)) {      System.out.println("存在状态 Status.Status0_正常");    } else {      System.out.println("不存在状态 Status.Status0_正常");    }    System.out.println("===============Status.Status0_下线================");    status.addStatus(EnumStatus.Status0_下线);    status.show();    if (status.hasFlag(EnumStatus.Status1_跑动)) {      System.out.println("存在状态 Status.Status1_跑动");    } else {      System.out.println("不存在状态 Status.Status1_跑动");    }

输出结果为

===============Status.Status0_空值================结果:     0 -> 0000000000000000000000000000000000000000000000000000000000000000===============Status.Status0_登陆================结果:     1 -> 0000000000000000000000000000000000000000000000000000000000000001不存在状态 Status.Status0_登陆===============Status.Status0_正常================结果:    100 -> 0000000000000000000000000000000000000000000000000000000000000100存在状态 Status.Status0_登陆===============Status.Status1_跑动================结果:   10100 -> 0000000000000000000000000000000000000000000000000000000000010100存在状态 Status.Status0_正常===============Status.Status0_下线================结果:    10 -> 0000000000000000000000000000000000000000000000000000000000000010存在状态 Status.Status1_跑动

到此为止。。ok,,,,

状态机,整理完成。。

 




原标题:Game中的状态机

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

中美最新消息!中国启动排除申请、美国新公布排除清单!:https://www.ikjzd.com/articles/97083
卑鄙无耻!华为受挫,三星和苹果坐收渔翁之利:https://www.ikjzd.com/articles/97085
FBA有门道!从这4个方面有效提升FBA运转效率!:https://www.ikjzd.com/articles/97089
亚马逊耍流氓!销售这类商品需谨慎!:https://www.ikjzd.com/articles/9709
马来西亚eWTP入快车道:农业有“大突破”、吉隆坡数字通关铺开:https://www.ikjzd.com/articles/97090
电子烟将出台标准野蛮生长期将很快结束:https://www.ikjzd.com/articles/97091
宠物梳专利查询分析:https://www.kjdsnews.com/a/1842293.html
温州旧货市场有玻璃柜卖吗?:https://www.vstour.cn/a/411246.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流