4

因此,在过去几天大量阅读 JS 之后(我才刚刚开始),我为我的项目找到了 3 个可行的选项,顺便说一句,这是一个游戏。我的游戏中将有大约 200 个项目,总共大约 30 个统计/属性。但是由于程序必须知道剑不会造成法术伤害,因此我必须为每个物品提供所有这 30 个属性,即使 90% 为 0。所以这就是我想出的,非常感谢任何建议:

var prop, obj = { Item1: "Boots", Item2: "Gloves", Item3: "Sword", Item4: "Cape" };

// 很确定我必须以某种方式重新制作它才能将属性放在那里,这可能不那么有用

function Item(hp, mp, dmg, spd, luk) {
    this.hp = hp;
    this.mp = mp;
    this.dmg = dmg;
    this.spd = spd;
    this.luk = luk;
}
var BigSword = new Item(0, 0, 50, 20, 10)

//我认为这可能是我最好的选择,所以尽可能少的变量?还是那不重要?每当我在更新函数中更新 totalHp 和 totalMp 和 totalDmg 等时,我想使用这个选项,我可以创建一个名为 theItem = BigSword 的局部变量,然后只需执行 theItem.hp、theItem.mp,这样就不必搜索太多对于变量,应该运行相对更快?对不起新手的问题,但 JS 甚至在函数中有局部变量吗?就像我做 var theItem = 不管一样,那么 theItem 将在函数之外为空?

itemNames = [ "Boots", "Gloves", "Sword", "Cape" ];
itemHp = [ 0, 0, 0, 50 ];
itemMp = [ 0, 30, 0, 0 ];
itemDmg = [ 0, 0, 50, 0 ];
itemSpd = [ 50, 0, 0, 0];

//这是我想出的另一个选项,有点难看,但如果只使用数组更快或更好,我不介意。

但请记住,就像我说的那样,总共有 200 多个项目,每个项目将有大约 30 个属性。你怎么看?

非常感谢您阅读并提供任何信息,非常感谢!提前致谢

4

3 回答 3

4

您最好的选择是拥有一个构造函数,就像您在第一个示例中所做的那样。但是,我会改变一些事情。首先,对于构造函数,您只是传入了很多数字。这很糟糕,因为很容易忘记数字的顺序。更好的方法是将一个对象传递给您的构造函数,这样您就可以标记每个属性:

function Item(props) {
    this.hp = props.hp;
    this.mp = props.mp;
    this.dmg = props.dmg;
    this.spd = props.spd;
    this.luk = props.luk;
}

var BigSword = new Item({
    hp: 0, 
    mp: 0, 5
    dmg: 0, 
    spd: 20, 
    luk: 10
});

这很好,但仍然很痛苦,因为您有各种不同的项目,而且正如您所说,您必须为每个项目定义 30 个属性,这既麻烦又耗时。在这一点上,你进入了更复杂的面向对象的领域。从这里你基本上有两个选择:继承和构造。

遗产

使用对象继承来正确定义对象可能是两者中最常见的一种,而且相当简单。本质上,您有一个对象的“类”,然后是每个类的子类。因此,您可能将魔法物品和非魔法物品分为两类。如果你有一条魔法腰带,也许你想让它继承 Magical Item 类的属性。另一方面,如果你有一把基本的未附魔剑,你会想让它继承自 Non-Magical Item 类。

但是假设你有魔法卷轴和魔法药水。都是魔法道具吧?因此,您需要创建一个名为 Potions 的类和一个名为 Scrolls 的类,它们都继承自 Magical Item 类。然后你可能有某些类型的药水。治疗药水,也许——“治疗盟友魔法药水”和“治疗自我魔法药水”。所以你需要为那些不同的类——等等。

Javascript 中的继承可以通过多种不同的方式完成,并且可以非常深入,所以我不会在我的帖子中讨论它。但是,如果您想走这条路,这里有一些有用的链接可以帮助您开始继承:

作品

组合是一个大量借鉴其他松散类型语言的概念,例如 Python,它非常广泛地使用它。组合背后的基本思想是您有一个基对象类,并且每当您需要某种特定类型的对象时,您就可以向该基类添加行为或成员。这不像继承那么广为人知,但它绝对是我更喜欢的一种。

在 Javascript 中,它的工作原理是拥有一个基本构造函数 Item,然后拥有其他构造函数,这些构造函数将必要的行为添加到您的 Item。让我们看一下我用于合成的示例——创建治疗盟友的魔法药水。你在这里有几个不同的属性:魔法物品、药水、治疗。有了继承,你会做类似Item -> Magical -> Potion -> Healing Potions -> Allies. 但是,通过组合,您可以将多个行为添加到基 Item 类,而无需设置巨大的原型链:Affect AlliesPotionHealing

由于组合比继承简单一点(而且,我承认,我有偏见)我将在伪代码中设置一个快速示例:

// base item class
function Item(props) {
    this.someProperty = props.someProperty;
    this.someOtherProperty = props.someOtherProperty;
}

// potion behavior
function Potion(props) {
    this.amount = props.amount; // IDK what amount means, just some random potion property
    this.color = "green";
}

// healing behavior
function Healing(props) {
    this.amountToHeal = props.amountToHeal;
    this.cooldown = props.cooldown;
}

// behavior to affect allies
function AffectAllies(props) {
    this.allies = props.allies;
    for(ally in this.allies) {
        this.allies[ally].affect(props.affact);
    }
}

// at this point we have the various behaviors set up and we can create the Magical Potion of Heal Allies constructor:

function MassHealingPotion(props) {
    var self = this;

    this.amount = props.amount;
    this.potion = new Potion(props);
    this.effect = new Healing(props);
    this.AffectAllies = new AffectAllies({
        affect: function(ally) {
            self.potion.affect;
        },

        allies: player.allies;
    });
}

// you can now create a mass healing potion:
var potion = new MassHealingPotion({
    weight: 50,
    someProp: "someValue",
    someOtherProp: "someOtherValue"
    // and so on and so forth with whatever properties you want the potion to have
});

好吧,结果比我预期的要长一点,并且可能包含比我想要的更多的错误,但我希望这传达了构图的基本思想。

现在,更简单的对象创建甚至不是组合的最佳部分,因为您可以重用不同的行为。考虑一下你有一把神奇的剑,每当你发动攻击时,它就会治愈你的盟友。您所要做的就是给它 Healing 成员和 AffectAllies 成员和繁荣——治愈伙伴的魔法剑。有了继承,你必须在 Magical Items 类中创建一个 Swords 类(然后你会有两个不同的 Swords 类——一个用于非魔法剑,另一个用于魔法剑!Ew!),然后用 Healing 扩展它剑,等等等等。

您可以采用任何一种方式,继承或对象组合。两者对于您想要实现的目标同样有效。

但是性能呢?

200 件物品,每件有 30 个属性?不是问题。将它们全部粘在一个巨大的阵列/物体中,煮沸,捣碎,将它们粘在炖菜中。浏览器不在乎。不过,您最好的选择可能是一个对象:

var itemList = {
    bigSword: new BigSword(...);
    smallSword: new SmallSword(...);
}
于 2013-05-31T01:37:39.930 回答
2

我更喜欢对象。我将从一个简单的通用“项目”开始,然后通过“继承”具有原型的通用项目来构建特定项目。

这可能会减少代码冗余并显着提高可维护性。

Speedwise 我不知道,但我认为迭代 200*30 数组值也不是那么快。

于 2013-05-31T01:12:59.253 回答
2

您需要首先进行认真的设计工作。如果您只是开始编码(就像许多开发人员所做的那样),您只会到此为止并意识到您的设计存在根本缺陷并且需要重写应用程序。在早期阶段这并不重要,但是一旦你编写了几百行代码,它就会变得非常乏味。

无论如何都要编写代码来原型化,但你应该期望从中得到的只是设计提示,代码应该被丢弃。

您的项目列表(或目录)应该是一个具有添加、删除和更新项目的方法的对象。然后每个玩家(角色、化身等)只需要一份他们的物品和他们的状态的列表。应该有一个全局更新伤害或生命值或任何获取特定类型物品并将它们应用到特定类型玩家的函数(例如武器伤害敌人,食物复活玩家和朋友等)。

只有了解了所有的玩家和物品以及它们的属性和动作,你才能开始设计接口和方法,最后编写一些代码。

密切关注目标,应该是开发一款引人入胜的游戏,而不是仅仅编写几千行代码。

于 2013-05-31T01:35:21.380 回答