Я только что создал небольшую игру «Space Invaders», используя простой Javascript, и она прекрасно работает на моем MacMini 2018 года, но невероятно быстро на моем MacBook Pro 2021 года (в котором есть чип M1).
Поскольку я использую requestAnimationFrame()
для своего основного цикла анимации (в отличие от setInerval
), у меня есть полный контроль, я пошел дальше и снизил частоту кадров анимации WAAAY, буквально уменьшив ее с 60 кадров в секунду до 10 кадров в секунду - но она ВСЕ ЕЩЕ работает непомерно быстро на M1 MacBook Pro.
Я знаю, что мой конкретный MacBook Pro M1 имеет частоту обновления экрана 120 Гц — что может быть самым большим виновником и основной причиной проблемы, но если да, то как мне обойти это?
Буду признателен за любые советы и рекомендации.
Спасибо.
Я прочитал кучу сообщений, в которых говорилось, что requestAnimationFrame()
— гораздо лучший вариант, чем setInterval()
, потому что он более точен, занимает меньше памяти и т. д. Не могу вспомнить все причины, но общее мнение заключалось в том, что это гораздо лучший способ. Как будто я видел это не в одном или двух местах, а везде. Так что же заставляет тебя говорить это?
Пожалуйста, опубликуйте stackoverflow.com/help/minimal-reproducible-example, с которым мы можем работать.
Да, requestAnimationFrame()
действительно гораздо лучший вариант для анимации. Вам просто нужно принять во внимание фактическое время, прошедшее между двумя вызовами. Затем, например, зная скорость и дельту времени, вы можете рассчитать расстояние.
Вот очень упрощенный пример. Вы можете найти больше информации о «игровом цикле» или аналогичном термине в Интернете.
var dt, last
var speed = 0.2;
var totalDistance = 0
var maxDistance = 300
function frame(now) {
dt = last ? now - last : 0
update(dt)
render(dt)
last = now;
requestAnimationFrame(frame);
}
function update(dt) {
totalDistance += dt * speed;
if (totalDistance >= maxDistance || totalDistance <= 0) {
speed *= -1
}
totalDistance = Math.max(Math.min(maxDistance, totalDistance), 0)
}
function render(dt) {
element.style.transform = `translateX(${totalDistance}px)`;
}
requestAnimationFrame(frame);
#element {
width: 100px;
height: 100px;
border: 1px solid gray;
}
<div id = "element">Hello</div>
Хорошо, я уже кое-что из этого делаю: у меня уже есть код, который вычисляет точное количество миллисекунд, прошедших между каждым вызовом requestAnimationFrame()
, и я стараюсь НЕ отображать другой кадр, если это время МЕНЬШЕ желаемого. 16,6667 мс, потому что это означает, что все происходит СЛИШКОМ БЫСТРО (и я знаю, что это работает) - НО... Я посмотрю на ваш код и посмотрю, делаете ли вы что-нибудь другое. Я скажу, что общее расстояние, которое должны пройти мои Космические захватчики, должно быть фиксированным (я почти уверен), поэтому я не знаю, хочу ли я, чтобы оно каждый раз пересчитывалось...
Вам следует использовать код, который позволит вам более точно контролировать время, например
setTimeout()
иsetInterval()
.