2015-02-27 1 views
2

Я написал небольшую 2D-игру в javascript, которая использует сетку, где игрок начинает в позиции [0,0] и может перемещать почти бесконечное расстояние в любом направлении.Отрицательные координаты в сетке на основе игры

Теперь я хочу реализовать A * pathfinding, но у меня возникли проблемы с поиском лучшего способа сохранить мир со всеми его различными препятствиями, врагами и ландшафтом. Это то, о чем я уже пробовал или думал.

Массив массивов

Здесь я храню мир в массиве массивов [x][y].

var world = [[]]; 
world[312][11] = 0; 
world[312][12] = 0; 
world[312][13] = 1; 
world[312][14] = 1; 
... 

Это прекрасно работает с A * pathfinding! Легко и очень быстро получить доступ к определенной координате и заполнить мир. В приведенном выше примере я просто храню проходимую (0) или непроходимую (1) местность, но я могу хранить почти все, что захочу. Однако это не очень хорошо работает с отрицательными координатами, например, если мои игроки находятся в [-12][-230]. Отрицательные ключи в массиве javascript на самом деле не являются частью массива, они не будут включены в world.length или world[3].length, и, насколько я понимаю, это общая плохая практика и может также повлиять на производительность. Я где-то читал, что если вы используете отрицательные ключи в своем массиве, вы делаете это неправильно. Я по-прежнему не мог бы передать весь мир в функцию A * по очевидным причинам. Просто небольшая часть, близкая к моему игроку, но координаты будут соответствовать позициям в массиве, с которыми легко работать.

отдельный массив массивов только для A * Pathfinding

Это где я нахожусь сейчас. У меня есть отдельная сетка 50x50 под названием pathMap = [[]], то есть только используется для поиска пути.

var pathMap = [[]]; 
pathMap[0][0] = 0; 
pathMap[0][1] = 0; 
pathMap[0][2] = 1; 
pathMap[0][3] = 1; 
... 

Она начинается в pathMap[0][0] и идет в pathMap[50][50] и работает в качестве наложения на моей текущей позиции, где я (как игрок) всегда будет находиться в центральном положении. Мои real координаты могут быть чем-то вроде [-5195,323], но это переводит на pathMap[25][25], и все, что близко ко мне, помещается в путьМарт по отношению к моей позиции. Теперь это работает, но это огромный беспорядок. Все переводы от одной координаты к другой взад и вперед заставляют мой мозг болеть. Кроме того, когда я получаю путь назад от A *, я должен перевести каждый его шаг назад в фактическую позицию, в которой мой элемент должен перемещаться в реальном мире. Я также должен заполнить один и тот же объект на 2 разных сетках при каждом обновлении, что также ухудшает производительность.

Массив объектов

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

var world = []; 
world[0] = { x: -10, y: 3, impassable: 0 }; 
world[1] = { x: -10, y: 4, impassable: 0 }; 
world[2] = { x: -10, y: 5, impassable: 1 }; 
world[3] = { x: -10, y: 6, impassable: 1 }; 
... 

Прекрасно работает с отрицательными значениями x или y! Однако в этом массиве не так легко найти, например, [10,3]. Мне нужно пройти весь массив, чтобы искать объект, где x == 10 и y == 3 вместо очень простого и быстрого подхода world[10][3] в первом примере.Кроме того, я не могу полагаться на то, что координаты находятся в правильном порядке, используя эту версию, сортировка становится сложнее, так же как и другие вещи, которые намного проще с массивом массивов.

Перестроить игру, чтобы всегда быть на положительной стороне

Я бы предпочел не делать этого, но я рассмотрел размещение игроков, начиная позиции на что-то вроде [1000000,1000000] вместо этого, и делают отрицательные координаты вне пределов. Кажется неудачным, если мне нужно устранить видение, которое у меня есть бесконечность, чтобы сделать работу по обращению с меньшим количеством кода. Я знаю, что всегда будут какие-то верхние или нижние ограничения, но я просто хочу начать с [0,0], а не с некоторой произвольной координатой по причинам, связанным с массивом.

Другое?

В javascript есть ли другой вариант, который работает лучше и не описан выше? Я очень открыт для предложений!

Есть ли передовая практика для подобных случаев?

+0

Будет ли это работать, если вы сделаете мир объекта с ключом будучи 'X; Y':' мир = {}; мир ['- 10; -10'] = 0'? Или создавайте объекты объектов, поэтому 'world [10] [10]' будет работать как массив. – elmigranto

+0

Интересно! Подобно * массиву объектов * версии с простотой, чтобы найти определенную координату массива * массивов *. Мне это нравится, но по какой-то причине он чувствует себя грязным. Я думаю, что это конкатенация и разделение ключа, который меня отталкивает. –

+0

'world = {}; мир [-10] = {}; мир [-10] [- 10] = 0'. Вам нужно будет сохранить свои собственные свойства 'length' и методы Array.prototype (если вам нужно что-то вроде' forEach' в вашем 'мире'). Это можно сделать при генерации или с помощью специального метода для добавления координат в 'world' или с помощью seters/getters. Я не думаю, что было бы много штрафа по сравнению с «Array [Array]», поскольку массивы - это в основном объекты с разными прототипами. – elmigranto

ответ

0

У вас есть три системы координат необходимо различать:

  • мировые координаты.
  • мировая модель/поиск путей (массив).
  • Координаты экрана.

экрана системы координат зависит от:

  • видового экрана = холст. (ширина, высота в пикселях).
  • a camera = (x, y) центр в мировых координатах + видWidth (в мировых координатах).

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

Возможно, вы захотите использовать Object.defineProperty для определения свойств, которые обеспечат свободный интерфейс.

var canvas = ... ; 
var canvasWidth = canvas.width; 
var canvasHeigth = canvas.heigth; 


var world = { 
       width : 1000, // meters 
       height : 1000, // meters 
       tileSize : 0.5, // height and width of a tile, in meter 
       model : null, // 2D array sized (width/tileSize, XtileSize) 
      }; 
// possibles world coordinates range from -width/2 to width/2 ; - height/2 height/2. 

var camera = { 
       x : -1, 
       y : -1, 
       viewWidth : 10, // we see 10 meters wide scene 
       viewHeight : -1 // height is deduced from canvas aspect ratio 
       }; 
camera.viewHeight = camera.viewWidth * canvasWidth/canvasHeight ; 

Тогда ваш персонаж выглядит следующим образом:

// (x,y) is the center of the character in centered world coordinates 
// here (0,0) means (500,500) world coords 
//     (1000,1000) array coords 
//     (320, 240) screen coords in 640X480 
function /*Class*/ Character(x, y) { 
    var _x=x; 
    var _y=y; 
    var _col=0; 
    var _row=0; 
    var _sx=0.0; 
    var _sy=0.0;   
    var dirty = true; 
    Object.defineProperty(this,'x', 
           { get : function() {return _x; } 
           set : function(v) { _x=v; 
                dirty=true; } }); 
    Object.defineProperty(this,'x', 
           { get : function() {return _y; } 
           set : function(v) { _y=v; 
                dirty=true; } }); 
    Object.defineProperty(this,'col', 
           { get : function() { 
               if (dirty) updateCoords(); 
               return _col; } }); 
    Object.defineProperty(this,'row', 
           { get : function() { 
               if (dirty) updateCoords(); 
               return _row; } }); 
    Object.defineProperty(this,'sx', 
           { get : function() { 
               if (dirty) updateCoords(); 
               return _sx; } }); 
    Object.defineProperty(this,'sy', 
           { get : function() { 
               if (dirty) updateCoords(); 
               return _sy; } }); 
    function updateCoords() { 
     _row = ((_x + 0.5 * world.width)/ world.tileSize) | 0 ; 
     _col = ((_x + 0.5 * world.height)/ world.tileSize) | 0 ; 
     _sx = canvasWidth * (0.5 + (_x - camera.x)/camera.viewWidth) ; 
     _sy = canvasHeight * (0.5 + (_y - camera.y)/camera.viewHeight) ; 
     dirty = false;    
    } 
} 
+0

Это было фантастическое разъяснение моего * «Отдельного массива массивов только для пути поиска» * - вариант, который я уже использую. Кажется, это просто вопрос, что я работаю с несколькими различными системами координат и заставляю его работать. –

 Смежные вопросы

  • Нет связанных вопросов^_^