构造具有大量数据的对象的更好方法(C ++)

时间:2018-04-09 15:39:01

标签: c++

编辑1:我正在使用一些有用的答案来处理解决方案,我会在我开始工作后立即更新帖子。

我正在用C ++中的几个同学为我的成绩最后一个项目制作视频游戏(我已经学习了6个月左右的语言)并且我们正在清理代码。

视频游戏是 RTS (实时策略),和其他人一样,我们有一堆单位,它们的行为方式相同,但它们有很多属性。实际上我们的构造函数代码(对于单位)看起来像(准备好大量的垃圾代码):

Unit::Unit(SceneNode *layer, int32_t id, Enumeration::UnitType type){
switch (type) {
        // Basic melee soldier
        case Enumeration::UnitType::StandardM:
                moveSpeed = 420;
                attackDamage = 15;
                attackRange = 100;
                attackSpeed = 1;
                viewRadius = 450;
                maxHP = 80;
                currentHP = 80;
                recruitingTime = 5;
                happiness = -10;
                citizens = -10;
                armyLevel = Enumeration::ArmyLevel::Footmen;
                attackEvent = "event:/UnitAttack/Drorania_melee_S";
                moveEvent = "event:/UnitMovement/Drorania_melee_S";
                selectEvent = "event:/UnitSelect/Drorania_melee_S";
                metalCost = Enumeration::UnitCost::MeleeFootmenMetalCost;
                crystalCost = Enumeration::UnitCost::MeleeFootmenCrystalCost;
                path = L"media/unitModels/Drorania/Melee_Soldier_Drorania.obj";
                setModel(layer, path);
                troops = new Troop(layer, path, 4, ID);
                //tex = new Texture("./media/textures/Drorania/Unit/drorania_melee_soldier.jpg");
        break;
        //Advanced melee soldier (mounted)
        case Enumeration::UnitType::AdvancedM:
            if (breed == Enumeration::BreedType::Drorania) {
                moveSpeed = 530;
                attackDamage = 21;
                attackRange = 140;
                attackSpeed = 1;
                viewRadius = 450;
                maxHP = 140;
                currentHP = 140;
                recruitingTime = 10;
                happiness = -10;
                citizens = -10;
                armyLevel = Enumeration::ArmyLevel::Mounted;
                attackEvent = "event:/UnitAttack/Drorania_melee_A";
                moveEvent = "event:/UnitMovement/Drorania_melee_A";
                selectEvent = "event:/UnitSelect/Drorania_melee_A";
                metalCost = Enumeration::UnitCost::MountedMeleeMetalCost;
                crystalCost = Enumeration::UnitCost::MountedMeleeCrystalCost;
                path = L"media/unitModels/Drorania/criatura_drorania.obj";
                //tex = new Texture("./media/textures/Drorania/Unit/drorania_criature.jpg");
                setModel(layer, path);
                //troops = new Troop(layer, path, 4, ID);
            } 
        break;
   /* More code*/
}
}

我确定有很多更好的方法来处理这些案件,但我并不深入研究语言功能(我的不好)。我很乐意清理代码的方式是初始化而不是使用枚举进行分配,但我还需要使用' .ob&分配 strings #39; 路径以加载模型,这就是为什么我认为枚举不是最好的情况。你们的想法是什么?

PS:对不起,如果我犯了很多英语错误。

PS2:我省略了很多代码,因为他们没有服务于问题目的。

PS3:我无法找到自己的其他人回答问题对我的案例有用,但也许我错过了一些商品。

3 个答案:

答案 0 :(得分:2)

这里可以使用一些模式,例如工厂模式以及Unit子类的多态层次结构,但这对于减少显示的代码没有太大作用(内部可能看起来非常事实上相似)。

相反,我建议将所有这些数据放在单独的数据文件中,而不是代码中。然后,您只需要一种方法将数据加载到Unit。如果有一些难以在数据文件中编码的单位类型知识,您仍然可以遵循类层次结构的想法。例如,可能有一个继承自UnitWithTroops的{​​{1}}类知道如何读取有关部队的数据。这需要多长时间取决于您的单位系统的(当前和未来)复杂性。

答案 1 :(得分:2)

定义文件格式,例如INI样式:

[StandardM]
moveSpeed = 420
attackDamage = 15
attackRange = 100
attackSpeed = 1
viewRadius = 450
maxHP = 80
currentHP = 80
recruitingTime = 5
happiness = -10
citizens = -10
armyLevel = Enumeration::ArmyLevel::Footmen;
attackEvent = event:/UnitAttack/Drorania_melee_S
moveEvent = event:/UnitMovement/Drorania_melee_S
selectEvent = event:/UnitSelect/Drorania_melee_S
metalCost = Enumeration::UnitCost::MeleeFootmenMetalCost
crystalCost = Enumeration::UnitCost::MeleeFootmenCrystalCost
path = media/unitModels/Drorania/Melee_Soldier_Drorania.obj

[Drorania]
moveSpeed = 530
etc...

解析此文件并构建您的单元。你会在这里保存很多代码。

答案 2 :(得分:0)

有用的经验法则是避免混合数据和逻辑。这听起来像是反OO的立场,但这根本不是我的意思。

考虑

UnitPrototype const *proto = lookup(type, breed);
// code using proto->speed,HP,path etc.
proto->setModel(layer);

现在游戏逻辑使用所有这些参数完全独立于所有硬编码值,因此单元构造函数更具可读性。

我只是handwaved存在的lookup函数仍然可以硬编码大量的魔术值(尽管这很难看),或者它可以使用声明式样式(仍然是硬编码但不与过程代码交错),或构建映射从启动时的配置文件 - 重点是它不再重要。您可以独立担心两个完全不同的问题。

NB。这里的部分技巧是看到一个" Unit"是两个的东西(然后将它们分开)。

有一个单元的原型,可能永远不会改变,并且是第一次创建时该单元的实例出现的方式。

然后是一个特定的单位实例,其HP和其他属性会随着时间而变化。

如果你的单位区分他们的统计数据和其他属性,而不是通过不同的逻辑,继承可能不是一个很好的模型。