3

我有以下模式来重复动画(本身由 x 帧组成), t 次:

sprite.prototype.loop = function(t,animation_name,frame_delay) {
    if(t > 0) {
        function next_run() {
            this.loop(t-1,animation_name,frame_delay);
        } 
        this.run(animation_name,frame_delay,next_run);
      }
    };

sprite.prototype.run = function(animation_name,frame_delay,frame_count,callback) {
    frame_count ||= 0;
    var s = this;
    if(frame_count < this.paths[animation_name].length) { // x frames
        setTimeout( function () {
            s.blit(s.paths[animation_name][frame_count]);
            s.run(animation_name,frame_delay,frame_count+1);
            }, frame_delay );
        }
    } else {
        if(!!callback) callback();
    }

super_mario.loop(10000,'mushroom_death',40);

显然,如果 x*t 大于最大堆栈深度,就会发生堆栈溢出。

问题:这种模式可以扩展到无限次运行动画的情况,还是有更正确的方法来做无限循环的情况?

4

2 回答 2

2

setTimeout不继承调用者的堆栈帧,所以你只需要担心t这里,虽然没有理由不能简单地迭代编写,这样堆栈大小就不是问题了:

sprite.prototype.loop = function(t, animation_name, frame_delay){
    while (t--){
        this.run(animation_name, frame_delay);
    }
};

但是,感觉这段代码并没有按照您的预期进行。这实际上是t并行运行动画时间,因为setTimeout调用run会相互交错。我不确定我能理解这将如何产生预期效果,因为每个t延迟回调都会在此处执行完全相同的blit操作,因此不会有明显的区别。

于 2013-03-10T10:03:51.907 回答
2

我会重写你的loop函数如下:

sprite.prototype.loop = function (t, animation_name, frame_delay) {
    var s = this;
    var frames = s.paths[animation_name];
    var x = frames.length;

    for (var i = 0; i < t; i++) {
        for (var frame_count = 0; frame_count < x; frame_count++) {
            setTimeout(function (frame_count) {
                s.blit(frames[frame_count]);
            }, (i * x + frame_count) * frame_delay, frame_count);
        }
    }
};

就是这样。不会有任何堆栈溢出,因为没有递归。

编辑:正如刚才提到的,您的代码还有另一个问题。两个相同的帧之间不会有任何延迟,因为您实际上同时调用setTimeout了所有相同的帧。因此,无论 的值是多少,动画都只会出现一次t

于 2013-03-10T10:05:02.263 回答