2013-04-08 13 views
1

Я хочу создать простую анимацию с гравитацией (http://jsfiddle.net/2pcr9/4/ протестирован в хромированном и firefox). Я делаю это в Javascript с холстом. Серьезность и скорость вычисляются с помощью переменного временного шага (: 46):Гравитация с длинной меткой времени (с javascript)

this.realDelta = (now - this.prevTime)/1000; 
this.realTime += this.realDelta; 

И каждый шар имеет этот код для вычисления скорости и положения (: 148):

this.vy += this.gravity * time.delta; 
this.x += this.vx * time.delta; 
this.y += this.vy * time.delta; 

Теперь это прототип работает без проблем при просмотре окна.

Но если вы скрываете текущее окно (переключитесь на другую вкладку своего браузера), то window.requestAnimationFrame останавливается. Если вы подождали 5 секунд и откройте окно, возобновится window.requestAnimationFrame. Проблема в том, что realDelta теперь составляет 5 секунд и делает слишком большую скорость.

я могу добавить проверку, чтобы не допустить realDelta быть больше, чем второй (: 46):

this.realDelta = (now - this.prevTime)/1000; 
if (this.realDelta > 1) { 
    this.realDelta = 1; 
} 
this.realTime += this.realDelta; 

, но это не решает проблему.

Теперь я не понимаю, как это исправить. Должен ли я проверить, скрыто ли окно и приостановить таймер (и возобновить таймер, когда окно снова будет видно). Или есть ошибка в моем вычислении скорости? Как другие игры html5 фиксируют эту проблему «dt» слишком большой?

Благодаря

+0

Выберите максимальный (или фиксированный) размер шага. Если фактический истекший интервал больше этого максимального временного шага, запустите свою физическую функцию несколько раз. – apsillers

+0

Я еще не слишком знаком с холстом, но я полагаю, что будет что-то близкое к событию on_resume. Если вы возобновите, просто установите время на последний использованный delta_t. Вы думаете, что это возможно? –

ответ

2

Внутри вашей функции дро, вы можете компенсировать пропущенные кадры, запустив функцию несколько раз, чтобы догнать:

var TIME_INTERVAL = 1000/60; 
var timeElapsed = 0; 
requestAnimFrame(draw, TIME_INTERVAL); 

function draw() { 
    timeElapsed += now - this.prevTime; 
    this.prevTime = now; 
    while(timeElapsed > TIME_INTERVAL) 
    { 
     timeElapsed -= TIME_INTERVAL; 
     // Run Draw 
    } 

    requestAnimFrame(draw, TIME_INTERVAL); 
} 

Конечно, если пользователь вкладками слишком долго, они могут вернуться к большому вычислений. Вы также можете рассмотреть возможность запуска резервного копирования в случае, если RequestAnimFrame недоступен:

var TIME_INTERVAL = 1000/60; 
var timeElapsed = 0; 
var backup = setInterval(draw, TIME_INTERVAL*5); 
requestAnimFrame(draw, TIME_INTERVAL); 

function draw() { 
    clearInterval(backup); 

    timeElapsed += now - this.prevTime; 
    this.prevTime = now; 
    while(timeElapsed > TIME_INTERVAL) 
    { 
     timeElapsed -= TIME_INTERVAL; 
     // Run Draw 
    } 

    backup = setInterval(draw, TIME_INTERVAL*5); 
    requestAnimFrame(draw, TIME_INTERVAL); 
} 
+0

Спасибо, это хороший способ справиться с этой проблемой! Извините, я не могу дать вам преимущество, у меня низкая репутация: D –

1

Используйте эти события JQuery для запуска/остановки ваши расчеты кадров:

(Вы можете попробовать без JQuery - прямой JavaScript, но X-браузер материал будет сводить вас с ума!)

Только в некоторых браузерах эти события срабатывают несколько раз, поэтому вы можете также установить флаг включения/выключения, чтобы вы просто реагировали на первый выстрел.

+0

Спасибо, это быстрый и легкий взлом, чтобы исправить проблему. –