2013-08-07 3 views
0

Я попытался создать прокручиваемую tilemap с объектом canvas, который автоматически вычисляет его размер относительно разрешения экрана и отображает фрагменты относительно позиции на карте большего размера.HTML5 Canvas smooth scroll tilemap

Я планировал переместить сгенерированные плитки и только нарисовать плитки, которые нужно нарисовать новыми.

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

Моя проблема:

Я не думаю, что это очень хорошо для производительности, чтобы изменить положение каждой плитки в полотне, я думаю, что это может быть решена с помощью getImageData() и putImageData(), но есть все еще осталась одна проблема:

Если я просто перемещу эти плитки и нарисую новые плитки, он всегда будет «прыгать» на 30 пикселей (1 плитка = 30x30), так что есть простой/эффективный технически хороший способ сделать это с гладкой , линейный эффект прокрутки?

ответ

3

Просто заполните доску с помощью drawImage или рисунка (последние требуют, чтобы вы использовали перевод, чтобы получить плитки в правильном положении).

drawImage принимает новый размер назначения в качестве аргумента, чтобы вы могли увеличить размер плиток.

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

function fillPattern(img, w, h) { 

    //draw the tile once 
    ctx.drawImage(img, 0, 0, w, h); 

    /// draw horizontal line by cloning 
    /// already drawn tiles before it 
    while (w < canvas.width) { 
     ctx.drawImage(canvas, w, 0); 
     w *= 2; 
    } 

    /// clone vertically, double steps each time 
    while (h < canvas.height) { 
     ctx.drawImage(canvas, 0, h); 
     h *= 2; 
    } 
} 

Спектакль хорош, как вы можете видеть в implementation this was used for (видеостена с живым масштабированием и черепицей).

К этому еще к тому, что у вас есть проект - вместо того, чтобы рисовать каждую плитку, как описано выше, вы можете просто нарисовать полотно на новое место и заполнить новый «пробел»:

ctx.drawImage(myCanvas, offsetX, offseY); 
fillGap(); 

Вы могли бы использовать обрезание с помощью drawImage, но холст будет обрезать это для нового внутри, так что нет никакой выгоды в обрезании изображения в JavaScript, когда вы перемещаете часть его за пределы холста.

+0

Спасибо за полезный текст! Моя сетка текстурирована, поэтому я не могу просто скопировать строки, мне нужно загрузить идентификатор текстуры для каждого поля из базы данных, и в настоящее время я ищу способ улучшить это, потому что я думаю, что это не так быстро. Идея с перемещением холста и заполнением пробела действительно помогла мне, но есть ли способ сделать то же самое с линейной анимацией? Или это возможно только при этом 30 раз/с, чтобы он выглядел как анимация? – cybrox

+1

@cybrox, к сожалению, нет прочь вокруг рисования x раз в секундах. Это то, как система делает это на низком уровне, а также то, как это делают видеоплееры. Кстати, видеоролик: здесь нужно предусмотреть все, но у него есть свои затраты, такие как память и начальное время загрузки. Вы также можете предварительно отобразить плитки, которые сгруппированы или не меняются, а также предварительно визуализировать большую область на экране за пределами экрана и делать вид кеша (связанного с двойной буферизацией). Использование 2 холстов также может быть полезным, когда у вас есть движущийся фон на одном нижнем холсте и статическая/другая анимация сверху. – K3N

+0

Спасибо за предложения. В настоящее время я использую несколько холстов, один для плиток и один для объектов на нем.Плитки хранятся в наборах тайлов, чтобы уменьшить количество загружаемых изображений, но всегда есть 10x10 плиток (= 300x300 px), упакованных в один набор плиток, и только часть всего изображения отображается как одиночная плитка на холсте. Однако, спасибо за вашу помощь, я постараюсь рассчитать все относительно данной скорости FPS и сделать ее гладкой :) – cybrox