0

我不太确定标题中的措辞是否准确地描述了我想要做的事情,请允许我解释一下:

假设在游戏中,您通过升级获得不同类型的积分。但是每个级别获得的每种类型的点数可以是任意的。

例如,我offensive每 2 级得到 3 分。但是我defensive在 2、4、5 和 6 级得到 2 分。除了第一级之外,每个级别都可能有 1supportive分。


现在这是我所做的:

//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()


对于这类问题,我通常想到的是这样的结构:

水平 总点
。. 1. . . . . 一个
。. 2. . . . . 乙
。. 3. . . . . 丙
。. 4. . . . . d
. . 5. . . . . e
以此类推,直到最高级别

在代码中,我也许可以这样做:

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];
    }
}
4

3 回答 3

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 设计模式

EDIT2:这是我试图解释的完整示例,希望对您有所帮助!

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);
于 2013-08-02T16:01:19.900 回答
1

为什么不将点存储在对象数组中 -

var pointsTable = [{offensivePionts: 1, defensivePoints: 1}, {offensivePoints: 1, defensivePoints: 2}]; //extend for any level

然后通过引用正确的属性来获得返回点 -

function getOffensivePoints(level) {
    return pointsTable[level]['offensivePoints'];
}

您可以使用 addLevel 等方法轻松扩展数据结构。

于 2013-08-02T15:31:43.003 回答
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变量。

于 2013-08-02T15:36:52.293 回答