diff options
Diffstat (limited to 'files/ru/games/anatomy/index.html')
-rw-r--r-- | files/ru/games/anatomy/index.html | 34 |
1 files changed, 17 insertions, 17 deletions
diff --git a/files/ru/games/anatomy/index.html b/files/ru/games/anatomy/index.html index 91949c9ac0..b3022fa527 100644 --- a/files/ru/games/anatomy/index.html +++ b/files/ru/games/anatomy/index.html @@ -18,17 +18,17 @@ original_slug: Games/Анатомия <p>Особенности игр.</p> -<p>Некоторые игры управляют своим циклом при помощи пользовательского ввода. Представьте, что вы разрабатываете игру типа <em>"найди разницу между этими двумя похожими картинками"</em>. Такого рода игры <strong>показывают</strong> пользователю две картинки; они <strong>получают</strong> их клики (или касания); они <strong>преобразуют</strong> ввод в успешный , не успешный, пауза, работа с меню, и так далее; в конечном итоге, в зависимости от данных действий, они <strong>вычисляют</strong> обновленное состояние сцены. Игровой цикл продвигается пользовательскими действиями и "спит" пока таковые отсутствуют. Это пример так называемой пошаговой игры, которая не зависит от постоянного обновления каждого кадра, а только от действий пользователя.</p> +<p>Некоторые игры управляют своим циклом при помощи пользовательского ввода. Представьте, что вы разрабатываете игру типа <em>"найди разницу между этими двумя похожими картинками"</em>. Такого рода игры <strong>показывают</strong> пользователю две картинки; они <strong>получают</strong> их клики (или касания); они <strong>преобразуют</strong> ввод в успешный , не успешный, пауза, работа с меню, и так далее; в конечном итоге, в зависимости от данных действий, они <strong>вычисляют</strong> обновлённое состояние сцены. Игровой цикл продвигается пользовательскими действиями и "спит" пока таковые отсутствуют. Это пример так называемой пошаговой игры, которая не зависит от постоянного обновления каждого кадра, а только от действий пользователя.</p> <p>Другие игры требуют контроля над каждым из минимально возможных индивидуальных временных интервалов. Те же принципы, что и выше, применяются с небольшим изменением: каждый кадр анимации продолжает цикл, и любое изменение пользовательского ввода фиксируется на первом доступном ходе. Эта покадровая модель реализована в так называемом <strong>основном цикле</strong>. Если ваша игра зацикливается на времени, то это будет её полномочия, которые будут соблюдать ваши симуляции.</p> <p>Но покадровое управление может и не понадобиться. Ваш игровой цикл может быть похож на пример <em>поиска отличий</em> и основан на входных событиях. Это может потребовать как ввода, так и симуляции времени. Он может даже зацикливаться на чем-то совершенно другом.</p> -<p>Современный JavaScript, как описано в следующих разделах, к счастью, позволяет легко разработать эффективный основной цикл выполнения один раз в кадр. Конечно, ваша игра будет оптимизирована настолько, насколько вы ее сделаете. Если что-то выглядит так, как будто оно должно быть прикреплено к более редкому исходу, то часто бывает хорошей идеей вырвать его из основного цикла (но не всегда).</p> +<p>Современный JavaScript, как описано в следующих разделах, к счастью, позволяет легко разработать эффективный основной цикл выполнения один раз в кадр. Конечно, ваша игра будет оптимизирована настолько, насколько вы её сделаете. Если что-то выглядит так, как будто оно должно быть прикреплено к более редкому исходу, то часто бывает хорошей идеей вырвать его из основного цикла (но не всегда).</p> <h2 id="Построение_основного_цикла_в_JavaScript">Построение основного цикла в JavaScript </h2> -<p>Лучше всего JavaScript работает с событиями и callback функциями. Современные браузеры стремятся вызывать методы по мере необходимости и бездействовать (или выполнять другие задачи) в промежутках. Привязать код к моменту, который для него подходит — это отличная идея. Подумайте о том, действительно ли ваша функция должна вызываться на строго определенном интервале времени, в каждом кадре или только после того, как произойдет что-то еще. Подумайте о том, действительно ли функцию нужно вызывать в определённом интервале времени, на каждый кадр или только после того, как что-то произойдёт. Больше конкретики с браузером в том, когда функция должна быть вызвана, позволяет ему лучше оптимизировать этот процесс. Так же, вероятно, это облегчит вам работу. </p> +<p>Лучше всего JavaScript работает с событиями и callback функциями. Современные браузеры стремятся вызывать методы по мере необходимости и бездействовать (или выполнять другие задачи) в промежутках. Привязать код к моменту, который для него подходит — это отличная идея. Подумайте о том, действительно ли ваша функция должна вызываться на строго определённом интервале времени, в каждом кадре или только после того, как произойдёт что-то ещё. Подумайте о том, действительно ли функцию нужно вызывать в определённом интервале времени, на каждый кадр или только после того, как что-то произойдёт. Больше конкретики с браузером в том, когда функция должна быть вызвана, позволяет ему лучше оптимизировать этот процесс. Так же, вероятно, это облегчит вам работу. </p> <p>Некоторый код должен выполняться кадр за кадром, так зачем же прикреплять эту функцию к чему-то другому, кроме графика перерисовки браузера? В Web, <code>{{ domxref("window.requestAnimationFrame()") }}</code> будет основой большинства хорошо запрограммированных покадровых основных циклов. Callback функция должна быть передана ему при вызове. Callback функция будет выполнена в подходящее время перед следующей перерисовкой. Вот пример простого основного цикла:</p> @@ -41,26 +41,26 @@ original_slug: Games/Анатомия main(); // Start the cycle</pre> <div class="note"> -<p><strong>Примечание</strong>: В каждом из методов <code>main()</code>, обсуждаемых здесь, мы планируем новый requestAnimationFrame перед выполнением нашего содержимого цикла. Это не случайно и считает лучшей практикой. Ранний вызов следующего <code>requestAnimationFrame </code>гарантирует, что браузер получит его вовремя, чтобы спланировать соответствующим образом, даже если ваш текущий кадр пропустит свое окно VSync.</p> +<p><strong>Примечание</strong>: В каждом из методов <code>main()</code>, обсуждаемых здесь, мы планируем новый requestAnimationFrame перед выполнением нашего содержимого цикла. Это не случайно и считает лучшей практикой. Ранний вызов следующего <code>requestAnimationFrame </code>гарантирует, что браузер получит его вовремя, чтобы спланировать соответствующим образом, даже если ваш текущий кадр пропустит своё окно VSync.</p> </div> -<p>Приведенный выше фрагмент кода содержит два оператора. Первый оператор создает функцию как глобальную переменную с именем <code>main()</code>.Эта функция выполняет некоторую работу, а также сообщает браузеру, что нужно вызвать следующий кадр с помощью <code>window.requestAnimationFrame()</code>. Второй оператор вызывает функцию <code>main()</code>, описанную в первом операторе. Поскольку <code>main()</code> вызывается один раз во втором операторе и каждый его вызов помещает себя в очерёдность действий, чтобы отрисовать следующий кадр, <code>main()</code> синхронизируется с вашей частотой кадров.</p> +<p>Приведённый выше фрагмент кода содержит два оператора. Первый оператор создаёт функцию как глобальную переменную с именем <code>main()</code>.Эта функция выполняет некоторую работу, а также сообщает браузеру, что нужно вызвать следующий кадр с помощью <code>window.requestAnimationFrame()</code>. Второй оператор вызывает функцию <code>main()</code>, описанную в первом операторе. Поскольку <code>main()</code> вызывается один раз во втором операторе и каждый его вызов помещает себя в очерёдность действий, чтобы отрисовать следующий кадр, <code>main()</code> синхронизируется с вашей частотой кадров.</p> <p>Конечно, этот цикл не идеален. Прежде чем мы обсудим способы его изменения, давайте обсудим, что он уже делает хорошо.</p> <p>Синхронизация основного цикла с тем, когда браузер рисует на дисплее, позволяет запускать цикл так часто, как браузер хочет рисовать. Вам предоставляется контроль над каждым кадром анимации. Это также очень просто, потому что <code>main()</code> - единственная функция, которая зацикливается. Шутер от первого лица (или подобная игра) представляет новую сцену один раз в каждом кадре. Вы не можете добиться большей плавности и быстродействия.</p> -<p>Но не стоит сразу предполагать, что анимация требует покадрового управления. Простые анимации можно легко выполнять даже с ускорением на GPU с помощью CSS-анимации и других инструментов, включенных в браузер. Их очень много и они сделают вашу жизнь проще.</p> +<p>Но не стоит сразу предполагать, что анимация требует покадрового управления. Простые анимации можно легко выполнять даже с ускорением на GPU с помощью CSS-анимации и других инструментов, включённых в браузер. Их очень много и они сделают вашу жизнь проще.</p> <h2 id="Создание_улучшенного_основного_цикла_в_JavaScript.">Создание улучшенного основного цикла в JavaScript.</h2> -<p>У нашего цикла есть две очевидные проблемы: <code>main()</code> загрязняет <code>{{ domxref("window") }}</code> объект (в нем хранятся все глобальные переменные) и код не оставляет нам возможность остановить цикл, если только вся вкладка не будет закрыта или обновлена. Для решения первой проблемы, если нужно, чтобы основной цикл просто выполнялся и вам не нужен легкий (прямой) доступ к нему, вы можете поместить его внутрь самовызывающейся Function Expression (IIFE).</p> +<p>У нашего цикла есть две очевидные проблемы: <code>main()</code> загрязняет <code>{{ domxref("window") }}</code> объект (в нем хранятся все глобальные переменные) и код не оставляет нам возможность остановить цикл, если только вся вкладка не будет закрыта или обновлена. Для решения первой проблемы, если нужно, чтобы основной цикл просто выполнялся и вам не нужен лёгкий (прямой) доступ к нему, вы можете поместить его внутрь самовызывающейся Function Expression (IIFE).</p> <pre class="brush: js notranslate">/* * Начинаем с точки с запятой в случае, если какая-либо строка кода выше данного примера * полагается на автоматическую вставку точки с запятой (ASI). Браузер может случайно решить, * что весь этот код начинается с предыдущей строки. Первая точка с запятой отмечает начало -* новой строки, если предыдущая не была пустой или завершенной. +* новой строки, если предыдущая не была пустой или завершённой. */ ;(function () { @@ -73,19 +73,19 @@ main(); // Start the cycle</pre> main(); // Вызов цикла })();</pre> -<p>Когда браузер наткнется на IIFE (Immediately Invoked Function Expression), он определит основной цикл и сразу же поставит его в очередь для следующего кадра. Он не будет привязан ни к какому объекту, и <code>main</code> (или <code>main()</code> для методов) будет неиспользуемым именем, доступным в остальной части приложения для определения чего-то другого.</p> +<p>Когда браузер наткнётся на IIFE (Immediately Invoked Function Expression), он определит основной цикл и сразу же поставит его в очередь для следующего кадра. Он не будет привязан ни к какому объекту, и <code>main</code> (или <code>main()</code> для методов) будет неиспользуемым именем, доступным в остальной части приложения для определения чего-то другого.</p> <div class="note"> <p><strong>Примечание:</strong> На практике распространено предотвращать следующий <code>requestAnimationFrame()</code> используя оператор if вместо вызова <code>cancelAnimationFrame()</code>.</p> </div> -<p>Чтобы остановить основной цикл, вам понадобиться отменить вызов <code>main()</code> с помощью <code>{{ domxref("window.cancelAnimationFrame()") }}</code>. Необходимо передать в <code>cancelAnimationFrame()</code> идентификатор последнего вызова <code>requestAnimationFrame()</code>. Давайте предположим, что функции и переменные вашей игры были определены в пространстве имен, которое вы назвали <code>MyGame</code>. В таком случае, основной цикл будет выглядеть следующим образом:</p> +<p>Чтобы остановить основной цикл, вам понадобиться отменить вызов <code>main()</code> с помощью <code>{{ domxref("window.cancelAnimationFrame()") }}</code>. Необходимо передать в <code>cancelAnimationFrame()</code> идентификатор последнего вызова <code>requestAnimationFrame()</code>. Давайте предположим, что функции и переменные вашей игры были определены в пространстве имён, которое вы назвали <code>MyGame</code>. В таком случае, основной цикл будет выглядеть следующим образом:</p> <pre class="brush: js notranslate">/* * Начинаем с точки с запятой в случае, если какая-либо строка кода выше данного примера * полагается на автоматическую вставку точки с запятой (ASI). Браузер может случайно решить, * что весь этот код начинается с предыдущей строки. Первая точка с запятой отмечает начало -* новой строки, если предыдущая не была пустой или завершенной. +* новой строки, если предыдущая не была пустой или завершённой. * * Давайте также предположим, что MyGame уже определена. */ @@ -100,7 +100,7 @@ main(); // Start the cycle</pre> main(); // Вызов цикла })();</pre> -<p>Теперь у нас есть переменная <code>stopMain</code>, объявленная в нашем пространстве имен <code>MyGame</code>, которая содержит идентификатор последнего вызова <code>requestAnimationFrame()</code> нашего основного цикла. В любой момент мы может остановить основной цикл, сказав браузеру, чтобы тот отменил запрос, соответствующий последнему маркеру.</p> +<p>Теперь у нас есть переменная <code>stopMain</code>, объявленная в нашем пространстве имён <code>MyGame</code>, которая содержит идентификатор последнего вызова <code>requestAnimationFrame()</code> нашего основного цикла. В любой момент мы может остановить основной цикл, сказав браузеру, чтобы тот отменил запрос, соответствующий последнему маркеру.</p> <pre class="brush: js notranslate">window.cancelAnimationFrame( MyGame.stopMain );</pre> @@ -108,7 +108,7 @@ main(); // Start the cycle</pre> <h2 id="Построение_более_оптимизированного_основного_цикла_в_JavaScript">Построение <em>более оптимизированного</em> основного цикла в JavaScript</h2> -<p>В конце контов, в JavaScript браузер выполняет свой собственный основной цикл, и ваш код существует на некоторых его этапах. В приведенных выше разделах описываются основные циклы, которые стараются не отнимать контроль у браузера. Их методы прикрепляют себя к <code>window.requestAnimationFrame(),</code> который запрашивает контроль над предстоящим кадром у браузера. Браузер решает, как связать эти запросы с их основным циклом. Спецификация <a href="http://www.w3.org/TR/animation-timing/">W3C для requestAnimationFrame</a> на самом деле точно не определяет, когда браузеры должны выполнять колбэки <code>requestAnimationFrame</code>. Это может быть преимуществом, поскольку позволяет поставщикам браузеров свободно экспериментировать с решениями, которые они считают лучшими, и настраивать их с течением времени.</p> +<p>В конце контов, в JavaScript браузер выполняет свой собственный основной цикл, и ваш код существует на некоторых его этапах. В приведённых выше разделах описываются основные циклы, которые стараются не отнимать контроль у браузера. Их методы прикрепляют себя к <code>window.requestAnimationFrame(),</code> который запрашивает контроль над предстоящим кадром у браузера. Браузер решает, как связать эти запросы с их основным циклом. Спецификация <a href="http://www.w3.org/TR/animation-timing/">W3C для requestAnimationFrame</a> на самом деле точно не определяет, когда браузеры должны выполнять колбэки <code>requestAnimationFrame</code>. Это может быть преимуществом, поскольку позволяет поставщикам браузеров свободно экспериментировать с решениями, которые они считают лучшими, и настраивать их с течением времени.</p> <p>Современные версии Firefox и Google Chrome (вероятно, и другие) <em>пытаются </em>подключить колбэки <code>requestAnimationFrame</code> к своему основному потоку в самом начале временного интервала фрейма<em>. </em>Таким образом основной поток браузера <em>пытается </em>выглядеть следующим образом: </p> @@ -116,12 +116,12 @@ main(); // Start the cycle</pre> <li>Запустить новый кадр (пока предыдущий обрабатывается на дисплее.).</li> <li>Пройтись по колбэкам <code>requestAnimationFrame</code> и вызвать их.</li> <li>Выполнить сборку мусора и другие задачи для каждого кадра, когда вышеупомянутые колбэки перестают контролировать основной поток.</li> - <li>Спать (если только какое-либо событие не прервет сон браузера) до тех пор, пока монитор не будет готов к вашему изображению (<a href="http://www.techopedia.com/definition/92/vertical-sync-vsync">VSync</a>), и повторить его.</li> + <li>Спать (если только какое-либо событие не прервёт сон браузера) до тех пор, пока монитор не будет готов к вашему изображению (<a href="http://www.techopedia.com/definition/92/vertical-sync-vsync">VSync</a>), и повторить его.</li> </ol> <p>Вы можете думать о разработке realtime applications, как о запасе времени для работы. Все вышеперечисленные шаги должны выполняться каждые 16 с половиной миллисекунд, чтобы не отставать от дисплея с частотой 60Гц. Браузеры вызывают ваш код таким образом, чтобы предоставить ему максимум времени для вычислений. Ваш основной поток часто запускает рабочие нагрузки, которые даже не находятся в основном потоке (Например, растеризация или шейдеры в WebGL). Большие вычисления могут выполняться на Web Worker-e или GPU одновременно с тем, как браузер использует свой основной поток для управления сборкой мусора, обработки асинхронных вызовов или других задач. </p> -<p>Пока мы обсуждаем распределение нашего временного бюджета, многие браузеры имеют инструмент под названием <em>High Resolution Time. Объект</em> {{ domxref("Date") }} больше не используется в качестве основного метода синхронизации событий, поскольку он очень не точен и может быть изменен системными часами. High Resolution Time, с другой стороны, подсчитывает количество миллисекунд начиная с <code>navigationStart</code> (при выгрузке предыдущего документа). Это значение возвращается в виде десятичного числа с точностью до миллисекунды. Он известен как <code>DOMHighResTimeStamp</code>, но для всех целей и задач считайте его числом с плавающей запятой. </p> +<p>Пока мы обсуждаем распределение нашего временного бюджета, многие браузеры имеют инструмент под названием <em>High Resolution Time. Объект</em> {{ domxref("Date") }} больше не используется в качестве основного метода синхронизации событий, поскольку он очень не точен и может быть изменён системными часами. High Resolution Time, с другой стороны, подсчитывает количество миллисекунд начиная с <code>navigationStart</code> (при выгрузке предыдущего документа). Это значение возвращается в виде десятичного числа с точностью до миллисекунды. Он известен как <code>DOMHighResTimeStamp</code>, но для всех целей и задач считайте его числом с плавающей запятой. </p> <div class="note"> <p><strong>Примечание</strong>: Системы (аппаратные или программные), которые не могу обеспечить точность в микросекундах, могут по крайней мере обеспечить точность в миллисекундах. Однако, они должны обеспечивать точность до 0,001 мс, если способны на это. </p> @@ -129,7 +129,7 @@ main(); // Start the cycle</pre> -<p>Это значение нельзя использовать само по себе, потому что оно относиться к неинтересному событию, но его можно вычесть из другой временной ветки, чтобы четко и точно определить, сколько времени прошло между этими двумя точками. Чтобы получить одну из этих временных меток, вы можете вызвать <code>window.performance.now()</code> и сохранить результат в переменную. </p> +<p>Это значение нельзя использовать само по себе, потому что оно относиться к неинтересному событию, но его можно вычесть из другой временной ветки, чтобы чётко и точно определить, сколько времени прошло между этими двумя точками. Чтобы получить одну из этих временных меток, вы можете вызвать <code>window.performance.now()</code> и сохранить результат в переменную. </p> <pre class="brush: js notranslate">var tNow = window.performance.now(); </pre> @@ -140,7 +140,7 @@ main(); // Start the cycle</pre> * Начинаем с точки с запятой в случае, если какая-либо строка кода выше данного примера * полагается на автоматическую вставку точки с запятой (ASI). Браузер может случайно решить, * что весь этот код начинается с предыдущей строки. Первая точка с запятой отмечает начало -* новой строки, если предыдущая не была пустой или завершенной. +* новой строки, если предыдущая не была пустой или завершённой. * * Давайте также предположим, что MyGame уже определена. */ |