У меня есть несколько старых программ, которые я снял с Windows-компьютера начала 90-х и попытался запустить их на относительно современном компьютере. Интересно, что они бегали с невероятной скоростью - нет, не с частотой 60 кадров в секунду, а с типом "о, боже мой!" быстрый. Я нажимал клавишу со стрелкой, и спрайт персонажа проносился по экрану намного быстрее, чем обычно. Временная прогрессия в игре происходила намного быстрее, чем следовало. Есть даже программы, разработанные для замедления вашего процессора, так что в эти игры можно играть.
Я слышал, что это связано с игрой в зависимости от циклов процессора или что-то в этом роде. Мои вопросы:
- Почему старые игры делают это, и как им это сходит с рук?
- Как новые игры не делают этого и работают независимо от частоты процессора?
FOR F IN 0 TO 1000; NEXT F;
Ответы:
Я полагаю, что они предполагали, что системные часы будут работать с определенной частотой, и привязали свои внутренние таймеры к этой частоте. Большинство из этих игр, вероятно, работали в DOS и работали в реальном режиме (с полным, прямым доступом к оборудованию) и предполагали, что вы используете систему iirc 4,77 МГц для ПК и любой другой стандартный процессор этой модели для других систем, таких как Amiga.
Они также использовали умные комбинации клавиш, основанные на этих предположениях, в том числе экономили крошечные ресурсы, не записывая внутренние циклы синхронизации внутри программы. Они также потребляли столько процессорной мощности, сколько могли - что было достойной идеей в дни медленных, часто пассивно охлажденных чипов!
Первоначально одним из способов обойти разную скорость процессора была старая добрая кнопка Turbo (которая замедляла работу вашей системы). Современные приложения находятся в защищенном режиме, а ОС стремится управлять ресурсами - они не позволяют приложению DOS (которое в любом случае работает в NTVDM на 32-разрядной системе) использовать весь процессор во многих случаях. Короче говоря, операционные системы стали умнее, как и API.
Основано на этом руководстве на ПК Oldskool, где логика и память подвели меня - это отличное чтение и, вероятно, более подробно объясняет «почему».
Такие вещи, как CPUkiller, используют как можно больше ресурсов, чтобы «замедлить» работу вашей системы, что неэффективно. Вам лучше использовать DOSBox для управления тактовой частотой, которую видит ваше приложение.
источник
game loop
. Есть в основном 2 метода. 1) Бегите как можно быстрее, масштабируйте скорость движения и т.д. в зависимости от скорости игры. 2) Если вы слишком быстры, подождите (sleep()
), пока мы не будем готовы к следующему «тику».Как дополнение к ответу Journeyman Geek (потому что мое редактирование было отклонено) для людей, которые интересуются частью кода / разработчиком:
С точки зрения программистов, для тех, кто интересуется, времена DOS были временем, когда каждый такт процессора был важен, поэтому программисты сохраняли код как можно быстрее.
Типичный сценарий, в котором любая программа будет работать с максимальной скоростью ЦП, выглядит следующим образом (псевдо-C):
это будет работать вечно, теперь давайте превратим этот фрагмент кода в псевдо-DOS-игру:
если
DrawGameOnScreen
функции не используют двойную буферизацию / V-синхронизацию (что было довольно дорого в те времена, когда создавались игры для DOS), игра будет работать с максимальной скоростью процессора. На современном мобильном i7 это будет работать примерно от 1 000 000 до 5 000 000 раз в секунду (в зависимости от конфигурации ноутбука и текущего использования процессора).Это означало бы, что если бы я мог заставить любую DOS-игру работать на моем современном процессоре в моих 64-битных окнах, я мог бы получить более тысячи (1000!) FPS, что слишком быстро для любого человека, чтобы играть, если физическая обработка «предполагает», что он работает между 50-60 кадров в секунду.
Разработчики текущего дня (могут):
*** это может быть возможно в зависимости от конфигурации видеокарты / драйвера / ОС .
Для пункта 1 нет примера, который я покажу, потому что на самом деле это не «программирование». Это просто использование графических функций.
Что касается пунктов 2 и 3, я покажу соответствующие фрагменты кода и пояснения:
2:
Здесь вы можете видеть, как пользовательский ввод и физика учитывают разницу во времени, но вы все равно можете получить более 1000 кадров в секунду на экране, потому что цикл работает максимально быстро. Поскольку физический движок знает, сколько времени прошло, он не должен зависеть от «никаких предположений» или «определенной частоты кадров», поэтому игра будет работать с одинаковой скоростью на любом процессоре.
3:
Что разработчики могут сделать, чтобы ограничить частоту кадров, например, до 30 кадров в секунду, на самом деле ничего сложнее, просто взгляните:
Здесь происходит то, что программа считает, сколько миллисекунд прошло, если достигнут определенный объем (33 мс), то она перерисовывает игровой экран, эффективно применяя частоту кадров около ~ 30.
Кроме того, в зависимости от разработчика он / она может ограничить ВСЕ обработки до 30 кадров в секунду с немного измененным кодом выше:
Есть несколько других методов, и некоторые из них я действительно ненавижу.
Например, используя
sleep(<amount of milliseconds>)
.Я знаю, что это один из способов ограничения частоты кадров, но что происходит, когда обработка вашей игры занимает 3 миллисекунды или больше? И тогда вы выполняете сон ...
это приведет к более низкой частоте кадров, чем тот, который только
sleep()
должен вызывать.Давайте, например, возьмем время сна 16 мс. это заставит программу работать на частоте 60 Гц. Теперь обработка данных, ввод, рисование и все остальное занимает 5 миллисекунд. Сейчас мы находимся на 21 миллисекунде для одной петли, что приводит к чуть менее 50 Гц, в то время как вы можете легко быть на 60 Гц, но из-за сна это невозможно.
Одним из решений было бы создание адаптивного сна в форме измерения времени обработки и вычитания времени обработки из требуемого сна, что привело к исправлению нашей «ошибки»:
источник
Одной из основных причин является использование контура задержки, который калибруется при запуске программы. Они подсчитывают, сколько раз цикл выполняется за известное время, и делят его для генерации меньших задержек. Затем его можно использовать для реализации функции sleep () для ускорения выполнения игры. Проблемы возникают, когда этот счетчик становится максимальным из-за того, что процессоры в цикле работают намного быстрее, поэтому небольшая задержка оказывается слишком маленькой. Кроме того, современные процессоры меняют скорость в зависимости от нагрузки, иногда даже в расчете на ядро, что делает задержку еще больше.
Для действительно старых компьютерных игр они просто бежали так быстро, как только могли, не взирая на ход игры. Это было больше в те дни, когда у IBM PC XT была турборежим, который по этой причине замедлял систему до 4,77 МГц.
Современные игры и библиотеки, такие как DirectX, имеют доступ к таймерам высокой прецессии, поэтому нет необходимости использовать калиброванные циклы задержки на основе кода.
источник
Вначале все первые ПК работали с одинаковой скоростью, поэтому не было необходимости учитывать разницу в скорости.
Кроме того, многие игры в начале имели довольно фиксированную загрузку процессора, поэтому маловероятно, что некоторые кадры будут работать быстрее, чем другие.
В настоящее время, с вашими детьми и вашими модными FPS-стрелками, вы можете смотреть на пол одну секунду, а в Гранд-Каньон на следующем, изменение нагрузки происходит чаще. :)
(И лишь несколько аппаратных консолей достаточно быстры, чтобы постоянно запускать игры со скоростью 60 кадров в секунду. Это в основном связано с тем, что разработчики консолей выбирают 30 Гц и делают пиксели в два раза ярче ...)
источник