Я создаю браузерную игру, похожую на Guitar Hero. Как это работает, setInterval установлен для выполнения каждой 16-й ноты в зависимости от темпа, который обычно составляет 100-150 миллисекунд. Функция, которую он выполняет, проверяет, есть ли заметка, которая должна быть проверена на нажатия клавиш пользователя.
Но я читал о том, как setInterval может страдать от дрейфа и может быть не очень точным. Для песни, которая длится 3-4 минуты и нуждается в точности 100 мс (если механика синхронизации даже немного выключена, это может очень расстраивать для пользователей), похоже, что это не может быть самым большим решением.
Так есть ли более конкретная альтернатива? T
Вероятно, было бы лучшей идеей рассчитать все в абсолютном времени. Итак, у меня есть var starttime = Date.now();
, а затем вычислить, где каждая нота должна быть var expected_note_time = starttime+beat_interval*beat_number
. Затем вы можете добавить слушателя при нажатии клавиши, а затем записать точное время нажатия клавиши. Если abs(time_pressed-expected_note_time) < ALLOWED_MISTAKE_VARIANCE
, затем добавьте эту точку в счет пользователя. Удачи.
и нуждается в точности 100 мс
Функция setInterval() будет дрейфовать из-за того, как построен javascript (цикл событий), и если вы заблокируете его с тяжелой задачей с интенсивным процессором, он будет задерживаться. Тем не менее, дрифт будет очень малым (меньше, чем мс), если вы сделаете это правильно.
Хорошим способом избежать этого было бы использование нескольких потоков, но это нелегко сделать в JavaScript.
Согласитесь, у setInterval есть некоторые проблемы, например, не важно, работает ли обратный вызов или нет, и не является гибким.
вы можете реализовать свой собственный метод:
function interval(func, wait, times){
var interv = function(w, t){
return function(){
if(typeof t === "undefined" || t-- > 0){
setTimeout(interv, w);
try{
func.call(null);
}
catch(e){
t = 0;
throw e.toString();
}
}
};
}(wait, times);
setTimeout(interv, wait);
};
эта функция имеет внутреннюю функцию, называемую interv, которая автоматически запускается через setTimeout, внутри interv - это замыкание, которое проверяет время повторения, вызывает обратный вызов и снова вызывает interv через setTimeout. В случае возникновения исключения из вызова обратного вызова прерывание интервала прекращается, и исключение будет выбрано.
вы можете использовать его так:
interval(function(){
// Code block goes here
}, 1000, 10);
которые выполняют часть кода 5 раз с интервалом или 10 секунд, и вы можете сделать что-то среднее между ними.
Вы можете кэшировать тики в начале песни, получить количество тиков с тех пор, посмотреть, существует ли заметка в этой точке.
Возвратите количество миллисекунд с 1970/01/01:
var d = new Date();
var n = d.getTime();
Результатом n может быть: 1502156888172
can suffer from drift
- я читал это утверждение раньше и решил проверить это утверждение, и обнаружил, по крайней мере в Firefox, что дрейфа как такового нет, есть джиттер