#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 градусам и всегда в одном направлении, ваша подпрограмма «мышь -> карта» может использовать алгоритм, подобный:
- вычислите i, j фрагмента, как вы делаете в данный момент (ваше конечное значение xmouse, ymouse)
- найдите высоту и угол наклона плитки в точках i, j
- учитывая высоту и угол, пересекает ли эта плитка луч выбора? Если это так, задайте lasti, lastj = i, j
- увеличьте / уменьшите i, j на один шаг по диагонали к просмотрщику
- мы упали с края карты? Если это так, верните lasti, lastj. В противном случае вернитесь к 2.
В зависимости от максимальной высоты плитки вам, возможно, придется проверять только 2 плитки, вместо того, чтобы идти до самого края карты.
3 — сложная часть, которая зависит от геометрии вашего мира. Нарисуйте несколько треугольников, и вы сможете это понять. Или вы могли бы попробовать посмотреть на функцию intersect_quadrilateral_ray() здесь.