2013-08-13 2 views
2

Я разрабатываю игру, которая использует requestAnimationFrame. Вот код для этого.requestAnimationFrame не отменяется

Game.prototype.startLoop = function (arg) { 

    var parent = this; 

    (function tick() { 

     parent.update(); 
     window.animationID = webkitRequestAnimationFrame(tick); 

    }()); 

}; 

Game.prototype.stopLoop = function() { 
    console.log('cancel the game now'); 
    window.webkitCancelRequestAnimationFrame(window.animationID); 
}; 

Проблема заключается в том, что я получаю сообщение, cancel the game now, однако игра продолжает работать, потому что animationFrame каким-то образом не отменяется. Я пробовал webkitCancelAnimationFrame, cancelAnimationFrame, webkitCancelRequestAnimationFrame и все версии для запроса рамки анимации в моем браузере: requestAnimationFrame, webkitRequestAnimationFrame. Ни одна из комбинаций не работает.

Странно, что если я запустил window.webkitCancelRequestAnimationFrame(window.animationID) в консоли инспектора webkit, игра прекратится, как ожидалось. Я добавил этот код window.webkitCancelRequestAnimationFrame(window.animationID); console.log('button test') в атрибут onclick кнопки DOM, и когда я нажимаю на него, игра останавливается, но когда я выполняю JS theDOMButton.click(), ничего не происходит, но я получаю сообщение «кнопка test».

Вот мой агент пользователя:

Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 

Вот jsfiddle:

http://jsfiddle.net/mJPMt/

После изменения этого: http://pastebin.com/ewDXBT9C это работает, но я думаю, что это странно, так как запрос анимации должен остановка без необходимости проверять с переменной в каждом цикле

+0

Прежде всего, используйте прокладку/полипол. Ваш код будет разбит на все, что не является webkit. – phenomnomnominal

+0

спасибо, но я использую webkit, поэтому на данный момент нет необходимости в pollyfills, они ничего не будут делать с моей проблемой. – richie

+0

Можете ли вы упростить код, который у вас есть, в небольшой тест, который может перепрограммировать проблему - в идеале отправьте его как скрипку? Есть хороший шанс, что какое-то другое взаимодействие вызывает проблему. – dc5

ответ

3

Вам нужно вызвать обновление после установки id

(function tick() { 
    id = webkitRequestAnimationFrame(tick); 
    update(); 
}()); 

В противном случае он останавливает старый, но новый все еще устанавливается.

FIDDLE

Для решения вопроса, что Винсент Piel приносит, вы всегда можете сделать update вроде promise. Вот этот подход: fiddle. Это похоже на то, что было в его ответе, за исключением того, что вам не нужно обладать булевым.

function update() { 
    var dfd = $.Deferred(); 
    x += 0.1; 
    y += 0.1; 

    if (x > 50) { 
     dfd.reject(); 
     return; 
    } 

    draw(); 
    dfd.resolve(); 

    return dfd.promise(); 
} 

(function tick() { 
    update().done(function() { 
     id = webkitRequestAnimationFrame(tick); 
    }); 
}()); 
+2

есть проблема, если обновление длится слишком много времени: другое обновление будет вызвано до предыдущего завершения. При длинных обновлениях и высокой частоте обновления (например, 120 Гц) это может произойти, особенно если злой сборщик мусора приостановит обновление. – GameAlchemist

+0

@VincentPiel Я обновил свой ответ, чтобы включить другое возможное решение, которое, безусловно, не будет иметь этой проблемы. – kalley

0

поведение, которое вы видите, совершенно нормально: что такое ha ppening - это то, что вы отменили метод update().
Итак, вы фактически отменяете предыдущий rAF, и вы запускаете еще один rAF, что бы ни случилось в обновлении.

(function tick() { 

    parent.update(); // here we cancel the last window.animationID 
    window.animationID = rAF(tick); // here we go again, we launch another rAF 

}()); 

Когда вы делаете это в консоли, вы отмените следующий RAF, следовательно, игра останавливается.

Поэтому вам нужно использовать логическое значение, чтобы остановить цикл и даже не сохранить идентификатор анимации.

я не знаю, как вы хотите, чтобы справиться с этим булево (замыкание/пространство имен/глобальная переменная), но это будет выглядеть так:

var animCancelled = false; 
(function tick() { 

    parent.update(); 
    if (!animCancelled) rAF(tick); 

}()); 
Смежные вопросы