我不太确定标题中的措辞是否准确描述了我要做的事情,请允许我解释一下:
假设在游戏中,你可以从升级中获得不同类型的积分。 但是每个级别获得的每种类型的点数都可以是任意的。
例如,
每2级我得3 offensive
分。
但是我在2级,4级,5级和6级得到2 defensive
分。
除了第一个,每个级别可能有1 supportive
个点。
现在这就是我所做的:
//Suppose I have my hero
var Sylin = new Hero();
Sylin.Level = 5;
//My goal is then to set
// Sylin.OffensivePoint to 6
// Sylin.DefensivePoint to 6
// Sylin.SupportivePoint to 4
Sylin.prototype.OffensivePoint = function() {
return 3*Math.floor(this.Level/2);
};
Sylin.prototype.DefensivePoint = function() {
var defPoint = 0;
for(var i=2; i <= this.Level; i++) {
//maximum level being 6
if(i==2 || i >= 4) {
defPoint += 2;
}
}
return defPoint;
};
Sylin.prototype.SupportivePoint = function() {
return this.Level - 1;
};
这一切都很好,但是如果最高级别被延长,点数列表将被更新,然后它变得非常笨拙,特别是如果我有这样的事情:
每3级有2分,但是9级和13级有3分或者显然缺乏模式,所以我不能像OffensivePoint()
所做的那样。
我对这类问题的一般想法是这样的结构:
级别 TotalPoint
。 。 1。 。 。 。 。一个
。 。 2。 。 。 。 。 b
。 。 3。 。 。 。 。 ç
。 。 4。 。 。 。 。 d
。 。 5。 。 。 。 。 Ë
等等,直到达到最高水平
在代码中,我可能会这么做:
Sylin.prototype.talentPoint = function() {
return readTalentPointTable(this.Level); //?
};
但是如果有20种等级可以获得5种不同类型的分数,那么这仍然会变得非常复杂,比如:/
。
。
修改
好的,我可以这样做:
var OffensivePointTable = [0,0,2,2,4,6,8,8,8,10,12];
function getOffensivePoint(level) {
return OffensivePointTable[level];
}
如果按照增加点数的级别或按上述运行总计存储数据会更容易吗?
。
。
编辑2
好的,我是否可以颠倒结构的顺序,首先查看类型,然后是水平?
var theTable = {
o: [0,1,0,1,1,0,0,0],
d: [0,0,2,0,2,0,2,0],
s: [0,1,2,3,4,5,6,7]}
//then your CalculateStats:
Sylin.prototype.CalculateStats = function() {
this.offensivePoint = 0;
for(var i=1; i<= this.Level; i++) {
this.offensivePoint += theTable[o][i];
}
}
答案 0 :(得分:1)
为什么不将点存储在对象数组中 -
var pointsTable = [{offensivePionts: 1, defensivePoints: 1}, {offensivePoints: 1, defensivePoints: 2}]; //extend for any level
然后通过引用corrent属性获得返回点 -
function getOffensivePoints(level) {
return pointsTable[level]['offensivePoints'];
}
您可以使用addLevel等方法轻松扩展数据结构。
答案 1 :(得分:1)
您可以使用一个对象来存储每个表格中要增加的点数(我没有使用您的确切数字,但您明白了这一点):
var LevelPoints = {
'1': {
o: 1,
d: 2,
s: 1
}
'2': {
o: 3,
d: 1,
s: 1
}
'3': {
o: 1,
d: 1,
s: 0
}
'4': {
o: 2,
d: 3,
s: 1
}
//etc.
}
例如,要访问级别2的进攻点增加,请使用LevelPoints['2'].o
。
我认为这需要大量的输入,但有时只是拥有所有数据会使事情变得更容易。使您的代码对您可读并且易于更改总是很好。它也可以作为一个快速参考 - 如果你想知道在6级获得多少攻击点,你可以立即知道。无需破译任何程序代码。当然,这是个人喜好。程序方法更快,使用更少的内存,所以这取决于你是否值得。在这种情况下,差异可以忽略不计,因此我建议采用数据驱动的方法。
另请注意,我使用var
来设置此对象。因为它可以被Sylin
构造函数的所有实例使用,所以将其设置为实例变量(使用this
)是浪费的,因为它将为Sylin
的每个实例创建对象。使用var
让他们共享它,节省内存。
或者,您可以在每个级别存储运行总计,但是IMO这需要更多的努力,没有充分的理由。写一个函数需要花费更少的时间:
Sylin.prototype.CalculateStats = function() {
this.OffensivePoint = 0;
this.DefensivePoint = 0;
this.SupportivePoint = 0;
for (var i = 1; i <= this.Level; i++) {
this.OffensivePoint += LevelPoints[i].o;
this.DefensivePoint += LevelPoints[i].d;
this.SupportivePoint += LevelPoints[i].s;
}
}
然后只要用户更改角色的级别,就可以运行此功能。无需传递关卡,因为该函数已经可以访问this.Level
变量。
答案 2 :(得分:1)
当然,您始终可以创建所有点的硬编码数组,但您也可以简单地对异常进行硬编码,并在可能的情况下坚持使用算法。
只是一个想法......这需要你的英雄跟踪他的观点,而不是动态地重新编译它们,但这可能是一件好事。
//have a map for exceptions
var pointExceptionsMap = {
'9': {
off: 3 //3 points of offense on level 9
}
};
Sylin.prototype.levelUp = function () {
var ex = pointExceptionsMap[++this.level];
//update offense points (should be in another function)
this.offense += (ex && typeof ex.off === 'number')?
ex.o /*exception points*/:
this.level % 2? 0 : 2; //2 points every 2 levels
};
然后升级,您执行hero.levelUp()
并获得积分hero.offense
。我没有测试任何东西,但那是个主意。但是,如果您需要能够直接设置级别,则可以使用setLevel
函数调用levelUp
适当的次数,但是,您必须使用修饰符才能使用也趋于平稳。
您还可以使用我当前的想法,找到实现异常算法的有效方法。例如,您仍然可以动态编译攻击点的数量,然后根据异常在该结果中添加或删除点。因此,如果您需要每2个级别获得2个积分,而级别9则需要3个积分,这意味着向编译点添加1个额外点。但是,因为当你达到更高级别时,你想保留该异常,你也必须跟踪所有添加的异常点。
编辑:此外,没有什么可以阻止您将函数用作新的异常算法而不是简单的数字,如果您打算使算法可配置,您可以简单地允许用户覆盖默认值。例如,您可以使用公共updateOffense
函数来封装逻辑,以便可以覆盖它。这与Strategy design pattern类似。
EDIT2:这是我试图解释的complete example,希望它有所帮助!
var Hero = (function () {
function Hero() {
this.level = 0;
this.stats = {
off: 1,
def: 0
};
}
Hero.prototype = {
statsExceptions: {
'3': {
off: 3 //get 3 points
},
'6': {
def: function () {
//some algorithm, here we just return 4 def points
return 4;
}
}
},
levelUp: function () {
++this.level;
updateStats.call(this, 1);
},
levelDown: function () {
updateStats.call(this, -1);
--this.level;
},
setLevel: function (level) {
var levelFn = 'level' + (this.level < level? 'Up' : 'Down');
while (this.level !== level) {
this[levelFn]();
}
},
statsFns: {
off: function () {
return (this.level % 2? 0 : 2);
},
def: function () {
return 1;
}
}
};
function updateStats(modifier) {
var stats = this.stats,
fns = this.statsFns,
exs = this.statsExceptions,
level = this.level,
k, ex, exType;
for (k in stats) {
if (stats.hasOwnProperty(k)) {
ex = exs[level];
ex = ex? ex[k] : void(0);
exType = typeof ex;
stats[k] += (exType === 'undefined'?
/*no exception*/
fns[k].call(this) :
/*exception*/
exType === 'function' ? ex.call(this) : ex) * modifier;
}
}
}
return Hero;
})();
var h = new Hero();
console.log(h.stats);
h.setLevel(6);
console.log(h.stats);
h.setLevel(0);
console.log(h.stats);
h.levelUp();
console.log(h.stats);
//create another type of Hero, with other rules
function ChuckNorris() {
Hero.call(this); //call parent constructor
}
ChuckNorris.prototype = Object.create(Hero.prototype);
//Chuck gets 200 offense points per level y default
ChuckNorris.prototype.statsFns.off = function () {
return 200;
};
//Not exceptions for him!
ChuckNorris.prototype.statsExceptions = {};
console.info('Chuck is coming!');
var c = new ChuckNorris();
c.setLevel(10);
console.log(c.stats);