#javascript #html #canvas
#javascript #HTML #canvas
Вопрос:
Я запустил прорывную игру в Canvas.
На данный момент я закодировал только отображение блоков и проигрывателя.
Когда игре потребуется обновляться (каждые 10 мс или около того), ей потребуется вызвать draw()
, который в данный момент собирается перерисовывать весь canvas на основе текущего состояния игрока, блоков и мяча.
Его производительность начинает становиться проблемой.
Разве никогда не бывает хорошей идеей перерисовывать весь холст на кадр? Должен ли я изменять свой код, чтобы рисовать только те разделы, которые меняются?
Комментарии:
1. Почему вы обновляете canvas со скоростью 100 кадров в секунду? Я думаю, 30 кадров в секунду было бы достаточно..
2. @BlueRaja Не знаю, я просто выбрал это число при написании вопроса. Я новичок в canvas / разработке игр.
3. В итоге я закончил это 🙂
Ответ №1:
Во-первых: Да, изменение вашего кода так, чтобы он рисовал только изменяющиеся разделы, может очень помочь, но вы всегда должны тестировать конкретные улучшения в своем собственном коде, поскольку производительность любой оптимизации варьируется в зависимости от приложения (иногда сильно).
Но не только рисование может вызвать замедление. Убедитесь, например, что вы не пересчитываете / реконструируете что-либо в своем цикле рисования, что никогда не меняется.
Кроме того, если у вас много объектов, не устанавливайте fillStyle
без необходимости, что означает, что требуется оптимизация путем установки заливки в один цвет, рисования всех объектов этого цвета, а затем установки второго цвета заливки и т.д.
Наконец, я бы посоветовал написать всю вашу игру (или большую ее часть), а затем вернуться и выполнить оптимизацию.
С Canvas требуется множество оптимизаций. Недавно я начал работу над руководством по повышению производительности, связанным с играми, надеюсь, оно будет готово к концу года.
Комментарии:
1. На мой взгляд, это лучше всего подводит итог идее. Постарайтесь поначалу не слишком беспокоиться об оптимизации — неразумно полностью игнорировать это, но не волнуйтесь слишком сильно. Другими узкими местами производительности JS, о которых следует помнить, являются вызовы функций (выполнение многих из них медленнее, чем встраивание, также Math.round по сравнению с использованием битовых сдвигов в round и т.д.), Чтение элементов из DOM (никогда не делайте этого, если можете избежать, всегда сохраняйте в переменной) — я написал несколько советов здесь: codeutopia.net/blog/2009/04/30 /…
Ответ №2:
Вам придется попробовать, чтобы убедиться, но я не согласен с обоими ответами здесь. В моих простых тестах попытка очистить и перерисовать только определенные области canvas приводит к немного худшей производительности, а не к улучшению.
Вы можете посмотреть мой тест здесь:http://phrogz.net/tmp/image_move_sprites_canvas.html
Однако это зависит от ваших потребностей. Если у вас есть сотни элементов, которые не нуждаются в обновлении, и только небольшая часть вашего canvas изменяет каждый кадр, возможно, будет полезно очистить и перерисовать только этот раздел.
Комментарии:
1. Интересные результаты… Я обнаружил совершенно противоположное при тестировании аналогичного подхода к рендерингу. Основное отличие, которое я вижу в моем, заключалось в том, что я использовал данные изображения canvas напрямую — getImageData и putImageData по сравнению с рисованием по изображению, как это делаете вы.
2. @Jani Очень удивительно, поскольку мои тесты показывают, что
get/putImageData
они намного медленнее .3. Однако я рисовал значительно более простые изображения, так что, возможно, это повлияло на то, как это работает
Ответ №3:
Разве никогда не бывает хорошей идеей перерисовывать весь холст на кадр?
Нет, иногда это совершенно хорошая идея
Его производительность начинает становиться проблемой
Но не тогда.
Тем не менее, ваш код не такой сложный, и в нем нет ничего, что могло бы вызвать очевидные массовые замедления. Как вы оцениваете его производительность?
Комментарии:
1. Спасибо за ваш ответ. Я тестировал в Chrome с примерно 15 открытыми вкладками, так что, скорее всего, это один из факторов замедления, которое я наблюдал 🙂
Ответ №4:
Сначала я бы убрал все это из init ():
canvas = document.createElement('canvas');
canvas.width = 400;
canvas.height = 300;
ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
Нет смысла заниматься этим каждую миллисекунду!
Во-вторых, посмотрите на это: http://paulirish.com/2011/requestanimationframe-for-smart-animating /
Комментарии:
1. Спасибо, но
init()
было бы вызвано один раз.draw()
это метод, который обновляет canvas.