尝试使用面向对象的Javascript进行建模

8
我对面向对象的编程范式还很陌生。
我正在尝试模拟某个游戏中的角色,其中有不同的级别、职业和许多装备选择等。
我的最终目标是创建一个“衣柜”,玩家可以打开网站,试穿一些装备,看看它们如何影响他们的参数,需要花费多少等等。
我已经编写了主要部分 (这里),但那是我第一次使用html、css和javascript编写的,现在整个代码混乱不堪。这一次我想开始得更好 :)
假设我们将模拟的角色有一个对象:
var Lord = function(){

    this.Level =       1;
    this.Gender =      'Male';
    this.Faction =     'Knight';

    this.Attack =      0;
    this.Defense =     1;
    this.SpellPower =  0;
    this.Knowledge =   0;
    this.Luck =        0;
    this.Morale =      1;
    this.Initiative =  0;

    this.addParameter = function(Parameter, amount){
        this[Parameter] += amount;
    };
    this.changeLevelTo = function(Level){
        this.Level = Level;
    };
    this.changeGenderTo = function(Gender){
        this.Gender = Gender;
    };
    this.changeFactionTo = function(Faction){
        this.Faction = Faction;
        //adjust default stats based on new faction
    };
};

我的问题是这样的: 骑士从1防御和1士气开始,不同的派系会给你不同的属性提升。这些值不能重新分配。 玩家在升级时还会获得一些属性点可以用于不同的参数,并且可以重新分配。
此外,玩家还可以装备一些装备,这些装备会提供属性加成,这些加成也无法重新分配(只能通过卸下来重新分配)。
我之前做的是创建了一堆数组,每个数组的索引对应每个参数,每个数组代表来自不同派系的默认属性提升、来自装备的总属性提升以及玩家手动分配的属性。然后我将每个索引相加,得到最终的参数数组进行显示。玩家只能在第三个数组中重新分配点数,而不能在其他数组中进行操作。
如何使用面向对象编程实现这个问题?
我已经阅读了一些基本概念(封装、继承、多态),但它们有些抽象,当我深入研究时,我真的不知道该怎么做:s
-
-
Responses
-
这个网站相当难用:o
好的,我会尝试看看qternion的答案能帮我解决问题吗:
var Faction = function(atk, def, sp, kn, luk, mor, ini){
    this.Attack =      atk;
    this.Defense =     def;
    this.SpellPower =  sp;
    this.Knowledge =   kn;
    this.Luck =        luk;
    this.Morale =      mor;
    this.Initiative =  ini;
}

var Knight = new Faction(0,1,0,0,0,1,0);
var Wizard = new Faction(0,0,0,1,0,1,0);

然后在主对象上,我会有以下操作。
    //this.Faction = 'Knight'
    this.Faction = Knight

    this.Defense = function(){
        return this.Faction.Defense + this.someOtherClass.Defense;
    }

我将会使用http://javascript.crockford.com/prototypal.html来改进以上内容的原型。

感谢大家的贡献 :)


骑士初始防御力为1 - 因此在你的对象字面量中将其设置为1... Defense: 0, => Defense: 1, - employee-0
1
为了提高您的Javascript面向对象编程技能,您可能还想查看这篇关于原型函数的SO帖子:https://dev59.com/ZWfWa4cB1Zd3GeqPmPu0 - Charlie Schliesser
1
由于您完全是面向对象编程的新手,我强烈建议您阅读以下博客文章,了解原型继承的重要性:http://aaditmshah.github.io/why-prototypal-inheritance-matters - Aadit M Shah
3个回答

2
你可以将统计值作为方法而非成员变量进行处理。这样,你就可以在调用给定统计值时进行计算,例如knight.defense()。而你的角色类中的defense()方法则可以调用faction类、equipmentSet类等中的defense()方法。这样做的好处是,例如当你决定要添加特权系统等内容时,可以随时添加额外的统计值修饰符。
每个faction类都可以覆盖其defense()函数来实现自己的修改器。
我不会认为这是最面向对象的方法,但作为JavaScript程序员,这是我自己会采用的方法。
附言:Pluto的回答也给出了如何获得可重用的“类”(而非单个对象)。正如我所提到的,我还会将Faction定义为一个类而非仅仅是一个字符串(可以使用instanceof进行类型检查)。
var Faction = function (){
    this.prototype.defense = function () { return this.Defense; };
    this.prototype.initStats = function () { this.Defense = 0;};
    this.initStats(this);
};

var Knight = new Faction ();
Knight.prototype.initStats = function () { this.Defense = 1;};

例如。

好的,等一下,既然我在展示之前要计算防御值,那么我可以直接使用防御方法的返回值,而不是计算它,将其赋值给防御属性,然后再使用属性本身吗?我想我现在开始有点明白了:D - Sylin
啊,忘了上面的内容吧,我刚意识到我可以创建一个派系对象,然后让每个单独的派系成为该对象的实例化!谢谢,我现在对此有更牢固的掌握了:D - Sylin
是的,我进行了编辑以解释如何使用继承来实现这一点,这至少更清晰了。 - qternion
1
是的,你可以在更合适的地方传播修饰符。例如,如果给定角色具有派系修饰符(由Faction.defense()给出)和装备修饰符以及一些临时状态修饰符,则所有这些修饰符都将添加到角色的防御方法中。但是,如果说,派系的修饰符可能会受到声望计量器或其他因素的影响,那么你希望knight.defense()不仅返回其静态修饰符,而且根据其声望值进行修改。 - qternion
让我们在聊天中继续讨论:http://chat.stackoverflow.com/rooms/33923/discussion-between-sylin-and-qternion。 - Sylin
显示剩余3条评论

2

如果您想要,可以保留数组。面向对象编程最重要的是封装,这归结于提供一种与您的角色对象交互的方式,而无需了解任何有关低级实现的信息。您希望处理的是对象,而不是数组或哈希表(即使在其下层实际构建对象时可能使用了它们!)。您需要编写像这样的代码:

var link = Knight();
link.equip(new MasterSword());
alert(link.getAttackPoints());

嗯,@qternion 已经先我一步回答了。所以我把这个答案变成一个维基!让我们释放SO的智慧。


我不太确定answer2wiki的含义,但如果它能帮助你和我,那我就没问题 :) - Sylin

2

只需将Lord改为函数(即var Lord = function() { /* current code */ }),并使用this.Level = 1;设置其属性。从现在开始,您可以像大多数面向对象编程语言一样使用new Lord()创建任意数量的Lord。

以下是实际应用的示例...

var Lord = function() {

    this.Level=1;
    this.Gender='Male';
    this.Faction='Knight';

    /* ... */

    this.addParameter=function(Parameter, amount){
        this[Parameter] += amount;
    };

    /* ... */
};
var a=new Lord();
var b=new Lord();

好的,也许我会改用这个。我原本计划使用这种符号表示设备等,而且只需要调整一个字符,所以我使用了字面符号表示法,但我对它不是很熟悉。 - Sylin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接