为角色制作装备时子类太多(角色扮演游戏)

Too many subclasses while making equipment for character (Role Playing Game)

我正在构建一个小型角色扮演游戏。一个角色有多个属性,比如:力量、魔法、射箭和防御。玩家还可以穿戴装备,如头盔、躯干、腿、靴子、手套和武器。每件装备都有自己的统计数据。例如,银色躯干 有 10 防御。

当角色有,比如15防御,他穿着银色躯干,他的防御现在是25。无论如何,为了穿装备,它需要生产的。目前我用抽象工厂模式设计它(见图)。

设计有很多class,大部分基本没什么用,比如青铜头盔银色躯干[=23] =] 等等,因为它们只有 class 统计数据的一个实例。

因此,我的问题是:什么是最好的装备制作方法,class用的越少越好。由于它是针对学校项目的,因此我最好使用设计模式。

在商业视频游戏中,许多具有不同属性和可能特殊效果的项目通常是通过脚本系统实现的。很难让它更具体,因为诸如脚本绑定和基于组件的架构之类的东西没有严格定义,并且因游戏而异。

您可以通过了解 (item-changing) 角色扮演游戏模组的工作原理来更好地了解这些系统的内部工作原理。例如,查看 Skyrim 的 "Papyrus" 绑定,或者更简单的示例查看 的 lua 绑定艾萨克:重生.

我会这样处理:

有一个抽象的 class 盔甲,所有头盔、躯干等都继承自该盔甲。然后你可以拥有单一的银牌和铜牌 class,可能也统一在 class ArmorType 下。我会根据它是哪种设备来获得某种修饰符,即 Bronze::modifier = 1.25;、Silver::modifier = 1.5; 等。这样,对于你拥有的每个新 ArmorType 或 Armor,你不必添加大量新的 classes。随着游戏的扩展,这种情况只会变得更糟。

当在 Armor subclasses 中完成实际统计计算时,它将是这样的:

//这是你的盔甲class.

    class Torso extends Armor {

        public Torso(ArmorType armorType) {
            this.armorType = armorType;
            this.baseStat = 10;
        }

        public double calculateStats() {
             return this.getBaseStat() * armorType.getModifier();
        }
    }

现在举个例子。如果 Torso 的基础属性为 10 护甲,Silver 的修正值为 1.5,那么这件护甲的最终防御力将为 15。当然,您可以根据自己的喜好调整这些数字或在计算中添加更多方面。这只是您可以执行的操作的一个简单示例。

如果您想保留原始设计中的 Stats 部分,我会将 Stats 对象放在 Armor class 中。因此,您实际上是在使用装饰器模式用 ArmorTypes 装饰您的 Armor classes。你也只是在你的数据 class 和你的 Subclasses of Armor 之间加了一层。

告诉我你的想法。

The design has a lot of classes, with most of them are basically useless, like Bronze Helmet, Silver Torso et cetera, because they only have an instance of the class Stats.

您似乎无缘无故地爆炸您的设计。整个层次结构可以只用一个名为 Equipment 的 class 代替。

public class Equipment {
    private Stats stats;
    private String equiptmentName;

    //constructors and getters and setters follow..
}

然后您的 Player class 可以有一个 SetEquipment,如下所示。每当安装或卸载设备时,您都会使用 Equipment 中的 stats 更新 Player 统计数据。

public class Player {
    private Set<Equipment> mountedEquipment;
    private Stats baseStats;

    public Player(Stats baseStats) {
       this.baseStats = baseStats;//set base stats for player
       mountedEquipment = new HashSet<Equipment>();
    }

    public void mountEquipment(Equipment equipment) { 
          baseStats.setMagic(baseStats.getMagic()+equipment.getStats().getMagic());

         //update base stats similarly for strength, hitpoints, etc
         mountedEquipment.add(equipment);

    }

    public void unmountEquipment(Equipment equipment) {

       baseStats.setMagic(baseStats.getMagic()-equipment.getStats().getMagic());
       //update base stats in a similar fashion for strength, hitpoints, etc
       mountedEquipment.remove(equipment);
    }

    public Set<Equipment> getMountedEquiptment() {
        return Collections.unmodifiableSet(mountedEquiptment);
    }

}

您实际上并不需要您在问题中显示的任何 Factory class,因为您可以将所有可能的 stats 添加到EquipmentPlayer class 每当您引入新的 Equipment 类型时。