Изометрический экран для отображения

#javascript #tiles #isometric

#javascript #плитки #изометрический

Вопрос:

Я пытаюсь выяснить, как я могу получить правильную «активную» плитку под мышкой, когда у меня есть плитки «ramp» и 1 высоты (см. Рисунок ниже).

Пример изометрического изображения

Когда мой мир плоский, все работает без проблем. Как только я добавляю плитку высотой, скажем, 1, вместе с рампой, возвращающейся к 0, моя процедура screen -> map по-прежнему выглядит так, как будто все «плоское».

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

Вот мой рендеринг карты (очень простой)

 canvas.width = canvas.width; // cheap clear in firefox 3.6, does not work in other browsers
for(i=0;i<map_y;i  ){
    for(j=0;j<map_x;j  ){
        var xpos = (i-j)*tile_h   current_x;
        var ypos = (i j)*tile_h/2  current_y;

      context.beginPath();
      context.moveTo(xpos, ypos (tile_h/2));
      context.lineTo(xpos (tile_w/2), ypos);
      context.lineTo(xpos (tile_w), ypos (tile_h/2));
      context.lineTo(xpos (tile_w/2), ypos (tile_h));
      context.fill();

    }
}    
  

И вот моя процедура мыши -> карта:

 ymouse=( (2*(ev.pageY-canvas.offsetTop-current_y)-ev.pageX canvas.offsetLeft current_x)/2 );
xmouse=( ev.pageX ymouse-current_x-(tile_w/2)-canvas.offsetLeft );
ymouse=Math.round(ymouse/tile_h);
xmouse=Math.round(xmouse/(tile_w/2));

current_tile=[xmouse,ymouse];
  

У меня такое чувство, что мне придется начать все сначала и внедрить картографическую систему на основе мира, а не простую процедуру экран -> карта.

Спасибо.

Ответ №1:

Ваше предположение верно. Для того, чтобы «выбирать» геометрию мира, ваша программа должна быть осведомлена о мире (а не только о конфигурации плитки базового уровня). То есть, без какого-либо представления о высоте плиток рядом с той, которая выбрана в данный момент (вашим текущим алгоритмом), нет способа определить, следует ли перехватывать соседнюю плитку (или еще более удаленную, в зависимости от разрешенной высоты) путем выбора луча.

У вас уже есть конечная возможная точка вашего луча выбора. Остается определить оставшуюся часть луча в мировом пространстве и проверить этот луч на предмет пересечений с мировой геометрией.

Ответ №2:

Если, как на картинке, ваш угол обзора всегда равен 45 градусам и всегда в одном направлении, ваша подпрограмма «мышь -> карта» может использовать алгоритм, подобный:

  1. вычислите i, j фрагмента, как вы делаете в данный момент (ваше конечное значение xmouse, ymouse)
  2. найдите высоту и угол наклона плитки в точках i, j
  3. учитывая высоту и угол, пересекает ли эта плитка луч выбора? Если это так, задайте lasti, lastj = i, j
  4. увеличьте / уменьшите i, j на один шаг по диагонали к просмотрщику
  5. мы упали с края карты? Если это так, верните lasti, lastj. В противном случае вернитесь к 2.

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

3 — сложная часть, которая зависит от геометрии вашего мира. Нарисуйте несколько треугольников, и вы сможете это понять. Или вы могли бы попробовать посмотреть на функцию intersect_quadrilateral_ray() здесь.