04丨风神界代码规范:背包卡牌与实体
创建日期:2025-01-11
更新日期:2025-02-04
阅读次数:62
需求
角色背包中有金币、树苗等。金币可堆叠,树苗可种植。
一阶:各种糟糕
糟糕的:背包道具无法排序
public class 背包类 {
public Dictionary<道具类, long> 所有道具 = new();
}
糟糕的:不方便存档
public class 背包类 {
public KeyValueList<道具类, long> 所有道具 = new();
}
糟糕的:容易出现运行时错误,出现未注册的string
public class 背包类 {
public KeyValueList<string, long> 所有道具 = new();
}
二阶:公私分离
public class 背包类 {
private KeyValueList<string, long> 所有道具 = new();
public void Add(道具类 X, long Y = 1) => 所有道具.FirstOrNew(t => t.Key == X.Name).Value += Y;
}
public class 道具类 {
public string Name;
}
public class 金币类 : 道具类 { }
public class 树苗类 : 道具类 {
public float 当前年龄;
public float 成熟所需;
public void 被种植(坐标类 X);
}
不允许直接对string操作,只允许通过Add函数来操作,这样避免了程序员疏忽导致的运行时错误。
核心思想:尽量无需运行,运行就一遍过、无报错。让所有错误都在编译时出现(即VS实时静态分析),让编译无错就运行无错。 因此,不要在代码中直接对引用关系复杂的字符串直接用双引号赋值。要么不用字符串,要么用字符串就设为Private、只允许通过API来设置。
但二阶还有新的问题:二阶默认,世界中的树苗,和背包中的树苗,是一个东西。这会导致诸多问题:
- 树苗在背包中无法堆叠,因为参数各不一致。
- 如果比较参数是否一致、一致的堆叠,那么每一个这种【既可以在背包中存在、又可以在世界中存在】的东西都需要写一份比较逻辑,代码冗余。
- 如果使用反射来自动比较所有参数,那么耗费性能。
- 如果就让道具不堆叠,那么:游戏中背包中可能有上万乃至上亿个道具,例如几亿的金币、矿石、工业流水线生产的几万套建筑物(使用金丹丹界或位面级空间戒指来承载,作为升级版背包),不堆叠的话没法看。
三阶:卡牌与实体分离
public class 背包类 {
private KeyValueList<string, long> 所有卡牌 = new();
private List<实体类> 所有实体 = new();
public void Add(卡牌类 X, long Y = 1) => 所有卡牌.FirstOrNew(t => t.Key == X.Name).Value += Y;
public void Add(实体类 X) => 所有实体.Add(X);
}
public class 卡牌类 {
public string Name;
}
public class 金币卡类 : 卡牌类 { }
public class 树苗卡类 : 卡牌类 {
public void Use(坐标类 X);(已屏蔽)
}
public class 实体类 { }
public class 树苗类 : 实体类 {
public float 当前年龄;
public float 成熟所需;
}
改动:
- 背包中的是卡牌,世界中的是实体。
- 对某坐标使用树苗卡,在那个坐标召唤一个实体树苗。
- 一些昂贵的背包,可以存放实体,实体不可堆叠(即:活物储物戒)。工业流水线生产的是卡牌。