Управление текстовыми картами в двумерном массиве для рисования на холсте HTML5

Итак, я делаю RPG на HTML5 просто для удовольствия. Карта является<canvas> (Ширина 512 пикселей, высота 352 пикселя | 16 плиток в поперечнике, 11 плиток сверху вниз). Я хочу знать, есть ли более эффективный способ нарисовать<canvas>.

Вот как у меня это сейчас получается:

How tiles are loaded and painted on map

Карта рисуется плиткой (32x32) с использованиемImage() кусок. Файлы изображений загружаются через простойfor цикл и положить в массив под названиемtiles[] быть покрашенным при использованииdrawImage().

Сначала мы загружаем плитки ...

enter image description here

и вот как это делается:

// SET UP THE & DRAW THE MAP TILES
tiles = [];
var loadedImagesCount = 0;
for (x = 0; x <= NUM_OF_TILES; x++) {
  var imageObj = new Image(); // new instance for each image
  imageObj.src = "js/tiles/t" + x + ".png";
  imageObj.onload = function () {
    console.log("Added tile ... " + loadedImagesCount);
    loadedImagesCount++;
    if (loadedImagesCount == NUM_OF_TILES) {
      // Onces all tiles are loaded ...
      // We paint the map
      for (y = 0; y <= 15; y++) {
        for (x = 0; x <= 10; x++) {
          theX = x * 32;
          theY = y * 32;
          context.drawImage(tiles[5], theY, theX, 32, 32);
        }
      }
    }
  };
  tiles.push(imageObj);
}

Естественно, когда игрок начинает игру, он загружает карту, которую он в последний раз остановил. Но здесь, это карта всех трав.

Прямо сейчас, карты используют 2D-массивы. Вот пример карты.

[[4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 1, 1, 1], 
[1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 13, 13, 13, 1, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 13, 13, 11, 11, 11, 13, 13, 13, 13, 13, 13, 13, 1], 
[13, 13, 13, 1, 1, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 1], 
[1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1]];

Я получаю разные карты, используя простойif состав. Как только 2d массив вышеreturnсоответствующий номер в каждом массиве будет окрашен в соответствии сImage() хранится внутриtile[], затемdrawImage() будет происходить и рисовать в соответствии сx а такжеy и раз это по32 рисовать на правильномx-y координат.

How multiple map switching occurs

В моей игре карты должны отслеживать пять вещей:currentID, leftID, rightID, upID, а такжеbottomID.

currentID: The current ID of the map you are on. leftID: What ID of currentID to load when you exit on the left of current map. rightID: What ID of currentID to load when you exit on the right of current map. downID: What ID of currentID to load when you exit on the bottom of current map. upID: What ID of currentID to load when you exit on the top of current map.

Что стоит отметить: если либоleftID, rightID, upID, или жеbottomID НЕ являются конкретными, это означает, что они0, Это означает, что они не могут покинуть эту сторону карты. Это просто невидимая блокада.

Таким образом, как только человек выходит из стороны карты, в зависимости от того, где он вышел ... например, если они вышли внизу,bottomID будет числоmap загрузить и, таким образом, быть нарисованным на карте.

Вот пример .GIF, который поможет вам лучше визуализировать:

enter image description here

Как вы можете видеть, рано или поздно, со многими картами, с которыми я буду иметь делоmany Идентификаторы. И это может стать немного запутанным и беспокойным.

Очевидным плюсом является то, что он загружает 176 плиток за раз, обновляет небольшой холст 512x352 и обрабатывает одну карту за раз. Дело в том, что идентификаторы MAP при работе со многими картами могут иногда сбивать с толку.

My question Is this an efficient way to store maps (given the usage of tiles), or is there a better way to handle maps?

Я думал по линии гигантской карты. Размер карты большой, и все это один двумерный массив. Однако область просмотра по-прежнему составляет 512x352 пикселей.

Вот еще один .gif, который я сделал (для этого вопроса), чтобы помочь визуализировать:

enter image description here

Извините, если вы не понимаете мой английский. Пожалуйста, спросите все, что у вас есть проблемы с пониманием. Надеюсь, я дал понять. Благодарю.

 higuaro10 июл. 2012 г., 05:53
AFAIK хранит "гигант" карты тайлов - это классический способ справиться с этим, но если ваша проблема связана с памятью, вы можете хранить индексы тайлов в бинарной маске, поэтому запись в вашей карте будет содержать несколько индексов тайлов (хотя помните, что javascript не имеет целые числа, все двойные, поэтому каждое значение на вашей карте занимает 8 байт, даже если вы используете значения 1, 3, 15 и т. д.)
 nn210 июл. 2012 г., 23:01
@TeemuIkonen Ваша идея звучит интересно, но да, основной доминирующей плиткой будет трава. Хорошая мысль.
 Teemu Ikonen10 июл. 2012 г., 06:05
Наши игры HTML5 используют RLE-кодировку для массива (например, если карта имеет ширину 40 плиток, а первая строка - только вода, значения в массиве - кортеж 1, 0, 39. 1 = вода, 0 начальный индекс, 39 конечный индекс. Доминирующая плитка Как и трава здесь, это CSS-фон с мозаичным холстом, который экономит 50% плиток. Я рекомендовал сделать большой холст и использовать CSS-перевод для его перемещения, чтобы избежать рисования всего на каждом шаге.
 Bergi18 июл. 2012 г., 04:11
+1 только за приятную анимацию :-)

Ответы на вопрос(1)

Решение Вопроса

Здесь есть несколько вещей, поэтому я отвечу на них по порядку.

...521 SEPARATE PNG FILES?

enter image description here

Используйте один. Только один. Может бытьsix, топы. Подумайте об этом, вы заставляете каждого клиента делать 500 запросов GET только для того, чтобы получитьtiles для игры? Это помешано.

Почти каждый крупный сайт использует спрайт-карты для сокращения запросов. Youtube, например, использует это одно изображение для всех своих кнопок:

enter image description here

Вы должны сделать то же самое.

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

Что касается вопроса производительности вашей карты, то для начала неплохо было бы использовать гигантские массивы. Это хороший способ справиться с этим, и я бы не стал изучать другие варианты, если ваше слово не очень, очень большое. Если он массивный, у вас может быть "куски" мира с размером 400x400 (или около того), и когда вы приходите к 400-й строке, вы начинаете использовать строку 0 следующего массива. Большинство массивов "в использовании" в любое время будет четыре, конечно, когда ваш герой будет на старом добромчетыре угла вроде места.

Местоположение игрока не будет трудным. Если бы он был на плитке 822, 20, это означало бы, что он в куске, представленном(2, 0) (если мы начинаем с(0, 0)). В частности, он должен быть в ячейке 22, 20 этого фрагмента. Без сложной математики, без ID. Нет необходимости отслеживать ID. Вам даже не нужно отслеживать, какой кусок является последним. Вы можете просто знать, что общий размер карты составляет, скажем, 1200x1200, и если он пытается перейти к (1201, 50), вам даже не нужно видеть, есть ли кусок(4, 0) существует. Вы сразу знаете, что он не может двигаться туда, карта имеет ширину всего 1200 плиток!

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

Как только вы доберетесь до производительности, я бы обо всем беспокоилсяexcept этот вопрос первым. В игре на холсте это действительно маловероятно быть узким местом. Чтение из массивов быстро. Большие массивы уже в памяти должны быть быстрыми. Тамshouldn't быть проблемой, и я бы не стал тратить время на ожидание, пока оно не представится.

EDIT: Пример перемещения окна просмотра с игроком:http://jsfiddle.net/kmHZt/10/

 12 июл. 2012 г., 05:46
+1 спрайт-карты очень удобны, как только вы их получите.
 17 июл. 2012 г., 14:44
Вот инструмент для генерации ваших спрайт-картwearekiss.com/spritepad быстро и легко.
 nn210 июл. 2012 г., 17:16
Хм, это имеет смысл. Благодарю.
 10 июл. 2012 г., 16:16
Я имею в виду положение(822, 20) ака плитка, которая находится в этом месте
 nn210 июл. 2012 г., 07:11
Что ты хочешь этим сказать:Player location wouldn't be hard. If he was at tile 822, 20 that would mean he is in the chunk represented by (2, 0) (if we're starting from (0, 0)). Specifically, he'd be in tile 22, 20 of that chunk., Я потерян. Плитка 822?

Ваш ответ на вопрос