在函数中访问'this'变量传递给setInterval / setTimeout

时间:2013-01-28 21:49:11

标签: javascript jquery setinterval

我正在创建一个简单的游戏,其角色可以跳跃,向右移动,向左移动。

我在跳转功能方面遇到问题,该功能使用setInterval

这是功能:

 jumpUp: function (speed) {
        setInterval(function () {
            this.yPos += 10;
            this.playerElement.css("top", '-=' + 10);
            alert("dude, im not moving....so stop trying"); //for some reson, this line works and other dont.
        }, 100);
}

我应该补充一点,代码在没有setInterval的情况下工作。当我添加setInterval时,我真的不知道为什么它不起作用。

我的问题:

  1. 什么阻止此代码运行?
  2. setInterval是一个让角色看起来像跳跃和着陆的好方法吗?或者我应该使用不同的方法吗?
  3. 编辑1:

    fiddle

4 个答案:

答案 0 :(得分:5)

问题在于您使用this。当您调用传递给setInterval的函数时,this将成为全局对象(浏览器中为window)。您需要在致电this时保留setInterval值。一种方法是将this的值存储到一个变量中,然后由匿名函数(这是一个闭包)将其关闭:

 jumpUp: function (speed) {
        var self = this;
        setInterval(function () {
            self.yPos += 10;
            self.playerElement.css("top", '-=' + 10);
        }, 100);
}

编辑:

要回答你的第二个问题,更好地设置精灵动画(比如你的角色)的方法是存储角色的速度,然后有一个游戏循环,根据该信息计算精灵的下一个位置。一个非常简单的例子如下:

// Somewhere else in the code:
function tick() {
    // move player by player.velocity.x and player.velocity.y

    // code to decelerate player gradually, stop player when they hit a wall/floor, etc...
    // A very simple example:
    if (player.velocity.y > 0) {
        player.velocity.y -= 1
    }

    // call next tick() (setTimeout, or preferably requestAnimationFrame)
}

// In the player code:
velocity: {x: 0, y: 0},
jumpUp: function () {
    this.velocity.y -= 10;
},
moveRight: function () {
    this.velocity.x += 10;
}

答案 1 :(得分:1)

正如darma和danronmoon指出的那样,你有一个范围问题。

请尝试以下代码:

jumpUp: function (speed) {
    var that = this;

    setInterval(function () {
        that.yPos += 10;
        that.playerElement.css("top", '-=' + 10);
    }, 100);
}

我添加了一个变量,用于维护对应该是什么的引用。

答案 2 :(得分:1)

除了你的关闭问题,这可能会引起不稳定的跳跃。

这是另一种观察时钟的模式,看看每次调用函数之间经过了多长时间(setInterval不一致):

jumpUp: function (speed) // speed in pixels per second
{
    var last = +new Date();
    var c = this;
    var jumptick = function ()
    {
        var interval = +new Date() - last;
        c.yPos += speed * interval;
        c.playerElement.css("top", c.yPos);
        if (/* condition for reaching maximum height */) speed = -speed;
        if (! /* condition for reaching ground */) setTimeout(jumptick);
            // could add an interval but this will lead to fastest frame rate
    };
    jumptick();
}

答案 3 :(得分:1)

Setinterval不是实现这一目标的好方法,因为它将使用大量的资源。 移动角色时还需要考虑帧速率,否则他将在快速机器/浏览器上快速移动并在慢速机器上慢速移动。

一个好方法是使用requestAnimationFrame方法。您可以在谷歌上找到一个javascript文件,使其与crossbrowser兼容。

然后,每次调用函数时,都需要检查帧之间经过的时间并相应地移动精灵。这是更多的工作,但这样,你的游戏将在任何机器上以相同的速度运行。