company_banner

Как раскрыть мощь HTML5 Canvas для игр

http://blogs.msdn.com/b/eternalcoding/archive/2012/03/22/unleash-the-power-of-html-5-canvas-for-gaming-part-1.aspx
  • Перевод
  • Tutorial


Браузеры, поддерживающие HTML5, и платформа HTML5 для Windows 8 Metro сегодня становятся серьезными кандидатами для разработки современных игр.

Благодаря canvas, у вас есть доступ к аппаратно-ускоренной поверхности, на которой вы можете отображать контент вашей игры и с помощью некоторых трюков и ухищрений вы сможете достигнуть великолепной производительности рендеринга до 60 кадров в секунду. Подобная непрерывность действительно важна в играх, так как чем плавнее игра (анимация), тем лучше чувствует себя игрок.

Цель данной статьи — дать вам несколько подсказок, как выжать максимум мощности из HTML5 Canvas. Статья состоит из двух основных частей [вы читаете первую]. David Rousset скоро опубликует вторую часть.

В статье я буду показывать ключевые идеи на одном и том же примере — это эффект 2D-туннеля, который я написал для Coding4Fun-сессии на TechDays 2012 во Франции.


На написание данного эффекта меня вдохновил мой код для Commodore AMIGA, который я написал, когда был молодым автором демосцен в далеких 80х :). Сегодня он использует только canvas и Javascript, хотя изначальный код базировался только на 68000 ассемблере:


Пример на JSFiddle (учтите, что текстура зашита в код).

Полный код доступен для скачивания тут: http://www.catuhe.com/msdn/canvas/tunnel.zip (копия на Я.Народ).

Целью данной статьи является объяснить, не как запрограммирован туннель, а как вы можете взять имеющийся код и оптимизировать его, чтобы добиться лучшей производительности в реальном времени.

Использование скрытого canvas для чтения данных изображения


Первая вещь, о которой я хочу поговорить, это то, как вы можете использовать canvas для оптимизации чтения данных изображения. Действительно, практически в каждой игре вам нужна графика для спрайтов или фоновых изображений. В canvas есть очень удобный метод для отрисовки изображений: drawImage. Эта функция может использоваться для вывода спрайта в canvas-элемент, так как вы можете указать области источника и назначения для отрисовки.

Но иногда этого не достаточно. Например, когда вы хотите применить какие-то эффекты к исходному изображению. Или когда исходное изображение не просто картинка, а более сложный ресурс для вашей игры (к примеру, карта, из которой вам нужно считывать данные).

В таких случаях вам необходим доступ к внутренним данным изображения. Но image-тег не предоставляет способа для считывания содержимого. Вот тут-то на помощь и приходит canvas!

В сущности, каждый раз, когда вам нужно считать содержимое изображения, вы можете использовать невидимый (не выводимый на экран) canvas. Ключевая идея заключается в том, чтобы загрузить изображение, и, когда оно загружено, вам остается только отобразить его на canvas-элемент, не вставленный в DOM. Теперь у вас есть доступ к [скопированным] пикселям исходного изображения через соответствующие пиксели canvas (что очень просто).

Код для этой техники выглядит следующим образом (используется в эффекте 2D-туннеля для чтения текстуры туннеля):

var loadTexture = function (name, then) {
    var texture = new Image();
    var textureData;
    var textureWidth;
    var textureHeight;
    var result = {};

    // on load
    texture.addEventListener('load', function () {
        var textureCanvas = document.createElement('canvas'); // off-screen canvas

        // Setting the canvas to right size
        textureCanvas.width = this.width; // <-- "this" is the image
        textureCanvas.height = this.height;

        result.width = this.width;
        result.height = this.height;

        var textureContext = textureCanvas.getContext('2d');
        textureContext.drawImage(this, 0, 0);

        result.data = textureContext.getImageData(0, 0, this.width, this.height).data;

        then();
    }, false);

    // Loading
    texture.src = name;

    return result;
};


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

// Texture
var texture = loadTexture("soft.png", function () {
    // Launching the render
    QueueNewFrame();
});


Использование возможности аппаратного масштабирования


Современные браузеры и Windows 8 поддерживают аппаратное ускорение canvas. Это, в частности, означает, что вы можете использовать GPU для масштабирования контента в canvas.

В случае с эффектом 2D-туннеля алгоритм требует обработки каждого пикселя canvas. К примеру, для canvas размером 1024x768 необходимо обработать 786432 пикселей. Чтобы обеспечить непрерывность отображения, это нужно делать 60 раз в секунду, что соответствует обработке 47185920 пикселей в секунду!

Очевидно, что любое решение, которое помогает вам уменьшить количество пикселей, приведет к заметному улучшению производительности.

Повторю, canvas предоставляет такое средство! Следующий код показывает, как использовать аппаратное ускорение для масштабирования внутреннего буффера canvas до внешнего размера DOM-объекта::

// Setting hardware scaling
canvas.width = 300;
canvas.style.width = window.innerWidth + 'px';
canvas.height = 200;
canvas.style.height = window.innerHeight + 'px';


Обратите внимание на разницу между размером DOM-объекта (canvas.style.width и canvas.style.height) и размером рабочего буффера canvas (canvas.width и canvas.height).

При наличии разницы между этими двумя размерами используются возможности железа для масштабирования рабочего буффера — в нашем случае это просто великолепная функция: мы можем работать в меньшем разрешении и позволить GPU смасштабировать результат, чтобы заполнить DOM-объект (с использованием прекрасного бесплатного фильтра размытия для сглаживания результата).

В данном примере рендеринг производится в области 300x200, а GPU масштабирует до размеров вашего окна.

Эта возможность широко поддерживается всеми современными браузерами, поэтому вы можете рассчитывать на нее.

Оптимизация цикла отрисовки


Когда вы разрабатываете игру, у вас, наверняка, должен быть цикл рендеринга, в котором вы отрисовываете все компоненты игры (фон, спрайты, очки и т.д.). Этот цикл — узкое горлышко в вашем коде и должен быть максимально оптимизирован, чтобы быть уверенным, что ваша игра работает быстро и плавно.

RequestAnimationFrame


Одна из интересных возможностей, пришедших с HTML5, это функция window.requestAnimationFrame. Вместо использования window.setInterval для создания таймера, вызывающего ваш цикл отрисовки каждые (1000/16) миллисекунд (чтобы достичь заветных 60fps), вы можете делегировать эту ответственность на браузер с помощью requestAnimationFrame. Вызов данного метода говорит, что вы хотите, чтобы браузер вызвал ваш код сразу же, как только будет возможно обновить графическое представление.

Браузер включит ваш запрос внутрь своего расписания отрисовки и синхронизирует вас со своим кодом отрисовки и анимации (CSS, переходы, и т.д.). Это решение также интересно в связи с тем, что ваш код не будет вызываться, когда окно не видно (свернуто, полностью перекрыто и т.д.).

Это может помочь с производительностью, так как браузер может оптимизировать параллельную отрисовку (например, если ваш цикл рендерига слишком медленный) и при этом выдавать плавные анимации.

Код довольно очевиден (обратите внимание на использование браузерных префиксов):

var intervalID = -1;
var QueueNewFrame = function () {
    if (window.requestAnimationFrame)
        window.requestAnimationFrame(renderingLoop);
    else if (window.msRequestAnimationFrame)
        window.msRequestAnimationFrame(renderingLoop);
    else if (window.webkitRequestAnimationFrame)
        window.webkitRequestAnimationFrame(renderingLoop);
    else if (window.mozRequestAnimationFrame)
        window.mozRequestAnimationFrame(renderingLoop);
    else if (window.oRequestAnimationFrame)
        window.oRequestAnimationFrame(renderingLoop);
    else {
        QueueNewFrame = function () {
        };
        intervalID = window.setInterval(renderingLoop, 16.7);
    }
};

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

var renderingLoop = function () {
    ...

    QueueNewFrame();
};


Доступ к DOM (Document Object Model)


Чтобы оптимизировать свой цикл отрисовки, вам следует использовать как минимум одно золотое правило: НЕ ОБРАЩАЙТЕСЬ К DOM. Хотя современные браузеры специально оптимизированы в этом месте, чтение свойств DOM-объектов по-прежнему слишком медленное для быстрого цикла отрисовки.

Например, в моем коде я использовал профилировщик Internet Explorer 10 (доступный в инструментах разработчика по F12) и результаты очевидны:

performance DOM

Как вы можете видеть, доступ к ширине и высоте canvas занимает очень много времени в цикле отрисовки!

Изначальный код выглядел так:
var renderingLoop = function () {


    for (var y = -canvas.height / 2; y < canvas.height / 2; y++) {
        for (var x = -canvas.width / 2; x < canvas.width / 2; x++) {

            ...

        }
    }
};


Вы можете заменить свойства canvas.width и canvas.height двумя переменными с заранее заведенными правильными значениями:

var renderingLoop = function () {

    var index = 0;
    for (var y = -<b>canvasHeight</b> / 2; y < <b>canvasHeight</b> / 2; y++) {
        for (var x = -<b>canvasWidth</b> / 2; x < <b>canvasWidth</b> / 2; x++) {
            ...
        }
    }
};


Просто, не правда ли? Возможно, что не очень просто понять, но, поверьте мне, это стоит попробовать!

Предварительные вычисления


Согласно профилировщику, функция Math.atan2 несколько медленная. На самом деле, эта операция не зашита внутрь CPU, так что среда выполнения JavaScript должна проделать некоторые операции, чтобы вычислить результат.

[пер.: Хотя, с технической точки, зрения можно предположить, что конкретная реализация JS-runtime может опираться на аппаратную инструкцию fpatan, этого априорно никто не гарантирует. Спецификация ECMAScript5 относительно математических функций говорит о том, что они (очевидно) являются аппроксимациями и рекомендует использовать алгоритмы математической библиотеки Sun Microsystems (http://www.netlib.org/fdlibm). В любом случае, какой бы ни была реализация функции atan2, это не делает ее элементарной и быстрой.]

performance atan2

В целом, если вы можете организовать предварительный расчет для некоторого долго работающего кода, это всегда хорошая идея. Здесь прежде, чем запустить мой цикл отрисовки, я рассчитываю значения для Math.atan2:

// precompute arctangent
var atans = [];

var index = 0;
for (var y = -canvasHeight / 2; y < canvasHeight / 2; y++) {
    for (var x = -canvasWidth / 2; x < canvasWidth / 2; x++) {
        atans[index++] = Math.atan2(y, x) / Math.PI;
    }
}


Массив atans далее может использовать внутри цикла отрисовки для явного повышения производительности.

Избегайте использования Math.round, Math.floor и parseInt


Пункт на счет использования parseInt имеет смысл в нашем случае:
performance parseInt

Когда вы работаете с canvas, для указания на пиксели необходимо использовать целочисленные координаты (x и y). Однако все ваши вычисления производятся с использованием чисел с плавающей точкой и рано или поздно вам нужно будет конвертировать их в целые числа.

JavaScript предоставляет функции Math.round, Math.floor или даже parseInt для конвертации чисел в целые. Но эти функции делают некоторую дополнительную работу (в частности проверяют диапазоны или проверяют, что значения действительно являются числам; parseInt вообще первым делом конвертирует свой параметр в строку!). Таким образом, внутри моего цикла отрисовки мне нужен более быстрый способ для конвертации чисел.

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

Исходный код был таким:
u = parseInt((u < 0) ? texture.width + (u % texture.width) : (u >= texture.width) ? u % texture.width : u);


Новый код выглядит так:

u = ((u < 0) ? texture.width + (u % texture.width) : (u >= texture.width) ? u % texture.width : u) >> 0;


Конечно, это решение требует, чтобы вы были наверняка уверены в корректности передаваемого числа :)

Финальный результат


Применение всех описанных оптимизаций приводит к следующему отчету:
final performance

Как видите, теперь код выглядит хорошо оптимизированным с использованием только ключевых функций.

Мы начали с такого оригинального неоптимизированного туннеля:


Пример на JSFiddle

И пришли к такому результату после оптимизации:


Пример на JSFiddle

[пер.: данные скриншоты сделаны на комьютере переводчика, на котором fps не достигает заветных 60fps, но крутится довольно близко к этому — около 50fps в IE10.]

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

comparing performance

Двигаясь дальше


Помня об этих ключевых моментах, теперь вы готовы к разработке быстрых и плавных игр для современных браузеров и Windows 8!

Microsoft

289,00

Microsoft — мировой лидер в области ПО и ИТ-услуг

Поделиться публикацией
Комментарии 88
    0
    И все равно на моем компе 14 FPS выдает всего. Правда у меня Win Vista…
      +5
      тоже 14 фпс — хром, семерка.
        0
        29 fps, на офисном хламе, хром, семерка.
        0
        В фф — 50-55 fps,
        хром и ie9 — 18-20
          0
          В FF, Ubuntu — 20-23 fps
          0
          13 FPS — Хром, 7ка.
            0
            14 fps, Chrome, Win 7
            +1
            У меня 4 FPS, и что? Вы думаете, что на разном железе должны быть одинаковые показатели?
            А вообще — JS и HTML 5 не готов для игр — подобная вещь может выдавать сотни fps используя нативный код на намного более слабых машинах.
              0
              Вот когда последний человек забудет об этом, JS и HTML5 станут «готовы» для игр
              0
              Ноутбук Lenovo Core i3 \ 8gb DDR3 \ видео Intel HM55 те же 14 FPS
                0
                Windows 7 64x
                  0
                  Chrome ))
              0
              Chrome 18.0.1025.142 @ Ubuntu 11.10
              Неоптимизированный код — 21fps
              Оптимизированный код — 25fps
                0
                Ага, сорри, обновил неоптимизированный код на исходный )
                –5
                Микрософт задолбал своей рекламой, извиняюсь.
                  +3
                  Этот комментарий относиться исключительно к навязчивой шапке Visual Studio, измененному лейауту страницы, и к посту не имеет отношения.

                  Когда портят привычные вещи это вызывает справедливое раздражение. Об этом должны знать создатели данной рекламы, поэтому минусующие — идите лесом.
                    +6
                    Это их блог, это благодаря им вы прочли эту статью. Так что… идите лесом?
                      0
                      Гм, я выразил сове мнение.
                      Мне молчать о том, что своей рекламой они похерели шрифты, я не сразу нашел ссылку «Лента» чтобы уйти со страницы.
                      То есть по вашему, если, к примеру, двери в магазин сделали по-дебильному, то мне нельзя об этом высказаться хозяину магазина, указав на недостатки?
                        +1
                        Хинт: «у вас не особенно удобно страница сделана, если честно — и я говорю это без маньяческого желания кого-то оскорбить или покричать о джинсе, которой и впомине нет».
                          0
                          Интересно, отреагировал бы владелец магазина на мягкотелое высказывание: «у вас не особенно удобно страница сделана сделаны двери». Пока не проматеришься — никто ведь пальцем не поведет.
                          Ок, сегодня навязчивая реклама, завтра что?
                            0
                            Дабы не доводить дело до троллинга, закрываю тему.
                            Просто обидно, что хабр становиться не удобным для читателей.
                  +2
                  37-39fps FF, Gentoo
                    +1
                    Chrome 18 — стабильные 14 fps
                    FF 10 — постоянно скачет в диапазоне примерно 27-32 fps
                    Причем одинаково и первый, и второй пример. Может ссылки попутаны?
                    WinXP, E6500, GeForce 520
                      0
                      Обновил только что до FF 11 — стало 32-37 fps
                      0
                      Оптимизированный — 38 фпс, неоптимизированный — 40 фпс. Странно всё это. Браузер ФХ 11.
                        0
                        Обновил исходный код в неоптимизированном случае.
                        0
                        20 fps (оптимизированный), Chrome 18 — MacOS
                          0
                          > молодым автором демо-сцен
                          > автором демо-сцен
                          > демо-сцен

                          сделайте меня развидеть это
                            –1
                            к сожалению множество людей путает демосцену как явление и демо как ее конечный продукт
                          0
                          неоптимизированный 3, оптимизированный 38 — заметная разница.

                          А самый большой скачок, судя по графику, даёт кеширование значений DOM свойств.
                            0
                            24 fps на HP ProBook 4530s. Довольно таки неплохой результат.
                            0
                            У меня оба варианта 25-30 fps). Chrome 18, mac os.
                              0
                              Спасибо за статью, очень наглядно.

                              p.s. Картинка в начале статьи заставила улыбнуться.
                                0
                                0 фпс — не оптимизированный
                                2 фпс — оптимизированный
                                iOS safari iPad2
                                  0
                                  Вот это меня и печалит. Почему такие тормоза? Где же «будущее» если HTML5 на iPad так себя показывает?
                                  Да и на маке в Safari рывки и fps 12
                                  Позор…
                                    0
                                    На айпадах лучше пока использовать DHTML (CSS2 & CSS3), у них там есть аппаратное ускорение. На втором айпаде я больше 11 фпс так и не смог выжать.
                                      0
                                      на айпадах в iOS 5 уже ускорен и Canvas.
                                        0
                                        Не спорю, однако пока что многие девайсы не позволяют его использовать. Ключевое слово «пока», и в каждом конкретном случае надо смотреть как на целевом девайсе ведет себя выбранный рендер.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                    +2
                                    i7-860, 18fps, Chrome.
                                    То есть то что на 7Mhz Amiga выдавало 60fps, тормозит на мощном 4х-ядерном разогнанном до 4Ghz процессоре при использовании JavaScript.
                                    Не увидел мощь HTML5.
                                      +1
                                      На 7мгц данный эффект мог работать в 60fps лишь в сильно уменьшенном разрешении.
                                      Если это вас как-то утешит :-)
                                        0
                                        Пример. 8bit, 3.5MHz, 64x32 но нужно учитывать что это multicolor т.е. помимо самого эффекта еще значительное время тратится на его правильный вывод. Впрочем вы и без меня все это знаете :)
                                          0
                                          Годный пример, но 50fps там нет
                                          DR на хабре detected =)
                                            0
                                            Ну muticolor эффект просто по определению не может быть НЕ 50fps :) Конечно возможно перестройка самого туннеля идет не каждый фрейм, но отрисовка обязана быть 50fps, по-другому работать не будет.

                                            DR forever :)
                                            +1
                                            Показалось что предыдущий эффект плавнее работал.
                                            Тут же метаболлы ещё вылетают потом.
                                            Понятно, что простой мультиколорный туннель во фрейм должен работать.

                                            Спектрум-читерская машина с чанковым экраном и читерским бордюром.
                                            www.youtube.com/watch?feature=player_detailpage&v=rIncbxgg6Jk#t=192s
                                            (корявость английского в скроллере вызывает у меня чувство невыносимого стыда, но писали уж как могли)
                                            Хотя на классической амиге тоже можно с коппером поиграть.
                                              0
                                              Думаю что на любой 8bit машине без читерства не сделаешь ничего достойного :)
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              Смотря что за Amiga, 320x200 (а не 240) было у самого первого поколения Amiga, еще в середине 80-х. Если брать семейство с AGA чипсетом (Amiga 1200, Amiga 4000) то там и по разрешению и по цветам все очень достойно, особенно для того времени когда они были выпущены. Сравнивая демки для Amiga и PC начала/середины 90-х годов (пока PC не ушел слишком далеко по скорости процессора) можно явно увидеть графическое превосходство Amiga.

                                              Да и Motorola 68040/68060 по вычислительной мощности тоже будут достаточны для обсчета подобного эффекта в нормальном разрешении.
                                                0
                                                >> 320x200 (а не 240)
                                                А вот и неправда =)
                                                320x256 и 352x288 в overscan
                                                640x512 и 704х576 в случае high-res/interlace
                                          0
                                          В Opera 11.62 показывает 10 fps в оптимизированном варианте. И ещё не корректно отображается, будто фрактал мальденброта пляшет позади(но это больше вопросы к создателям Opera). И по заголовку поста я ожидал увидеть игру.
                                            +1
                                            Спасибо за статью но «для разработки современных игр» я б заменил «для разработки игр технологически выполненых на уровне эпохи первых пентиумов»
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                  +1
                                                  У меня лично этот туннель ничего общего с играми не вызывает, соответственно и доверия к автору статьи.

                                                  Оптимизации полезные, но упущено парочка важных:
                                                  — не рисуйте на канвасе без необходимости.
                                                  — при множестве отрисовок использовать невидимый канвас как буфер.
                                                    0
                                                    Никаких аргументов.

                                                    — не рисуйте на канвасе без необходимости.
                                                    Почему?
                                                    — при множестве отрисовок использовать невидимый канвас как буфер.
                                                    Зачем?
                                                      +1
                                                      1. Чтобы лишний раз не вызывать перерисовку?
                                                      2. Чтобы не вызывать перерисовку при каждой отрисовке очередного элемента каждый раз, а «нарисовать» всё в память и вывести готовую картинку
                                                        0
                                                        Ответил ниже
                                                        0
                                                        Операции работы с экраном довольно дорогостоящие по времени. Тот же флеш автоматически определяет области перерисовки и поступает мудро, ведь зачем перерисовывать то, что не изменилось?

                                                        Отрисовка в буфер так же сокращает работу с экраном, так как передает уже сформированное изображение для вывода на экран. Это в случае, если надо обновлять весь экран.

                                                        Хотя уверен, что вы лучше знаете, ведь я все эти штуки и по вашим статьям учил;)
                                                          +2
                                                          1. С этим согласен — я подумал, что вы имеете ввиду «не используйте канвас впринципе»
                                                          2. Там есть хитрости. Решение из топика лучше отрисовывать сразу на результатирующий канвас, т.к. кешировать там по сути нечего.
                                                          Просто стоит заметить, что двойная буферизация с десктопа здесь, в html5 canvas не рациональна. Первое время я и сам заблуждался в её целесообразности. Браузер сам буферизирует вывод, а потом выводит в ближайший animation frame.
                                                          Скрытый канвас имеет смысл использовать для того, чтобы отрисовать тяжёлые вычисления, например вектор перевести в растр, или попиксельный эффект — чтобы отрисовывать обычное растровое изображение

                                                          Пример — у нас есть картинка, которую мы должны загнать в чёрно-белый и прогнать по экрану слева-направо. Лучше её в невидимый канвас очернобелить, а потом эту чернобелую картинку отрисовывать через drawImage, чем каждый кадр делать putImageData.

                                                          Аналогично, если есть, например, машинка, которая собирается из кучи векторных объектов — её лучше растеризировать и выводить из кеша растр, чем каждый раз рисовать вектора.
                                                            0
                                                            То есть использование скрытых канвасов рационально только для отдельных элементов (кеширование обработанных изображений или вектора)?

                                                            У меня был опыт что добавление бэкбуфера позволило чуть ли не в два раза увеличить количество fps, что для меня стало железным аргументом. Может не все браузеры буферизируют вывод? Или может операция по выводу в буфер браузера оказывается все равно дороже, чем в скрытый буфер?
                                                              0
                                                              А как вы потом буфер выводили на экран? drawImage source-буфера в буфер на странице или через replaceChild?
                                                                0
                                                                drawImage
                                                                  0
                                                                  clearRect, а потом drawImage особенно большого холста — это очень ресурсоёмкая операция, особенно без аппаратного ускорения. Особенно учитывая тот факт, что часто надо перерисовывать только небольшой квадратик размером, скажем, 50*50
                                                                    0
                                                                    clearRect не использовал, так как перерисовывал весь экран, но согласен что для мелких перерисовок буфер — лишнее.
                                                                      0
                                                                      Если у нас летит шарик на прозрачном фоне, то отрисовывая бекбуфер в новый буфер мы будем иметь все предыдущие кадры.
                                                                        0
                                                                        А если у нас поле изометрическое, с анимированными объектами, которые взрываются, двигаются и еще пользователь перетягивает игровое поле?
                                                                          0
                                                                          Если есть прозрачные участки — будет баг)
                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                              0
                                                                              в каких слоях, вы о чем?)
                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  0
                                                                                  Прошу прощения, но просто самого понятия слоев в канвасе нету, мало ли что вы могли иметь в виду, люди ведь разные бывают.

                                                                                  Задачи разные бывают, я вот столкнулся с такой, когда надо было перерисовывать все поле. Вы же предлагаете, как я понимаю, кешировать отображаемую анимацию в скрытых канвах?

                                                                                  P.S. Я пробовал как то использовать несколько канвасов доя отрисовки различных слоев — тормоза дичайшие были. Это в случае, если вы это имели в виду)
                                                        +1
                                                        Вообще, отличная демонстрация того, почему HTML5 вытеснит Flash для игр… лет через 5.
                                                          0
                                                          Thinkpad t520, интеловское видео.
                                                          Linux Debian Sid + Experimental.
                                                          Gnome-shell, Chromium 17.0.963.83.

                                                          На панели ноутбука — 34 fps.
                                                          На внешнем мониторе — 25fps.

                                                          Загрузка процессора — 45-50%.
                                                            0
                                                            Все соревнуются кого с какой скоростью засасывает в зеленый анус. Страшно.
                                                              0
                                                              Я не силён в геймдеве и задам вопрос.
                                                              Вот в случае статического ФПС при использовании setInterval, мы можем отрисовывать движущиеся предметы, передвигая их с заданой скоростью, например 4 пикселя за такт. В случае RequestAnimationFrame нам получается необходимо умножать скорость движения на время до предыдущего кадра. Если объектом много не скажется это на производительности в худшую сторону?
                                                                0
                                                                Примерно так. Но лучше все равно использовать RequestAnimationFrame, при этом логику и физику оставить на таймере (если это критично).
                                                                Кроме того, RequestAnimationFrame позволит избавиться от «захлебывания» на клиентской машине, когда она не успевает отработать один кадр и начинает отрабатывать другой — получаются жуткие тормоза, которых в принципе можно было избежать, поставив рендер либо на таймаут, либо на RequestAnimationFrame.
                                                                  0
                                                                  Ну вот я тоже подумал, что отрисовку отделить от остального.
                                                                  0
                                                                  Вот в случае статического ФПС при использовании setInterval, мы можем отрисовывать движущиеся предметы, передвигая их с заданой скоростью, например 4 пикселя за такт.

                                                                  Ошибаетесь. Никто не гарантирует стабильности изменения setInterval, потому всё-равно на перемножать на дельту. И нет, на производительности это практически не сказывается (в рамках погрешности)
                                                                    0
                                                                    Ну я бы не сказал, что погрешность setInterval влияет сильно. Вопрос производительности напрямую зависит от количества операций.
                                                                      0
                                                                      Влияет достаточно. Тем более, если это будет фоновая вкладка, то там ещё и интервал увеличится.
                                                                  0
                                                                  Рассказали бы все же еще, хотя бы вкратце, как работает эффект. А то смотрю на все эти 40.0 * Math.abs(Math.cos(angle)) и ничего не понимаю :(
                                                                    0
                                                                    В данном примере рендеринг производится в области 300x200, а GPU масштабирует до размеров вашего окна.
                                                                    Все хорошо пока соотношения сторон не меняются
                                                                      0
                                                                      Пример конечно интересный, но прямая работа с пикселями — это то чего избегать надо.
                                                                      Про канвас в данном топике имхо — не сказано ни слова.
                                                                        0
                                                                        Спасибо, помогло. Увеличил FPS своей демки до 60-и.
                                                                          0
                                                                          А мне вот что интересно на Windows 8 CP:
                                                                          9-11fps — Опера (11.62), причем отображается по краям красным цветом, и ежесекундные затыки.
                                                                          13fps — Хром (18.0.1025.151m) — стабильно, но замедленно
                                                                          Зато IE10 (10.0.8250.0) выдает 40-41 не меньше.

                                                                          Хитрые оптимизации однако)

                                                                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                          Самое читаемое