Рисование нескольких произвольных линий - это слишком дорого EaselJS

Я программирую HTML5 2D-игру с использованием EaselJS, которая выглядит как симулятор планеты / гравитации, и я решил проследить движение / орбиту планеты с помощью линии, которая следует за каждой планетой при ее движении. Вот быстрая демонстрация GIF:

Демонстрация того, что я хочу

Проблема в том, что если я создаю линию на каждом тике, холст становится полностью медленным (потому что он рисует много линий на каждом тике, что дорого), поэтому я переместил дорогой код в setInterval с интервалами 250 мс между циклами, и проблема остается, потому что, когда есть много форм, это создаст много линий на цикл. Кроме того, если я просто добавлю больше времени между циклами, результат начнет выглядеть... Minecraft-ish.

Демонстрация 750 мс интервалов между каждой петлей

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

Вот соответствующий код:

setInterval(function() {
    allObjs.forEach(function(obj1) {
        if (typeof obj1.xpast !== "undefined" || typeof obj1.ypast !== "undefined") {
            var trail = new createjs.Shape();
            trail.graphics.s("#fff").ss(1, "round").moveTo(obj1.xpast + .5, obj1.ypast + .5).lineTo(obj1.x + .5, obj1.y + .5);
            trail.alpha = 0.25;
            stage.addChild(trail);
            setTimeout(function() {
                createjs.Tween.get(trail).to({
                    alpha: 0
                }, 1000).call(function() {
                    stage.removeChild(trail);
                });
            }, 10000);
        }
        obj1.xpast = obj1.x;
        obj1.ypast = obj1.y;
    });
}, 750);

К сожалению, сейчас я не могу поместить свой код в JSFiddle.

1 ответ

Решение

При перерисовке холста каждого кадра (и очистке его, отражающем изменяющееся содержимое) векторные линии складываются очень быстро. Это связано с тем, что графические инструкции перерисовываются в каждом кадре. Векторы на Canvas не ускоряются аппаратно, поэтому использование этого подхода будет очень медленным, когда вы подходите ко многим линиям.

Лучший подход - кэшировать вектор, а затем рисовать только то, что является новым. Когда вы кешируете его, за кулисами создается новый элемент canvas, который используется вместо реальной графики. Это означает, что вы можете сделать его настолько сложным, насколько захотите, без каких-либо изменений в производительности.

  • Кэшируйте фигуру в нужном вам размере (может, размер холста?)
  • Нарисуйте новую графику для этого кадра
  • Обновите кеш (рисует содержимое графики на существующий кеш)
  • Очистить графику в следующий раз

Вот пример этого на GitHub:

Надеюсь это поможет!

Другие вопросы по тегам