#javascript #html #2d #game-engine
#javascript #HTML #2d #игровой движок
Вопрос:
Итак, у меня есть шестнадцатеричная сетка размером 100×100… Сетка рекурсивна, поэтому, когда вы прокручиваете влево после позиции ‘0,0’, она рисует строку ‘99,0’ и т.д… Моя проблема заключается в поиске алгоритма, который позволит мне вычислить, повторяю ли я цикл…
Пример: 96 — 97 — 98 — 99 — 0 — 1 — 2 — 3 — 4
У обоих из них начальные местоположения меньше, чем конечное местоположение, если бы я был в строке 2, а экран переместился в строку 98:
от 2 до 98 РАБОТАЕТ (98) — 100 = -2, затем -2-(2) = расстояние в 4
с 96 по 98 СБОЙ (98) — 100 = -2, тогда -2-(96) = расстояние 98 (правильно равно 2)
Оба они имеют конечные местоположения меньше, чем начальное местоположение, однако это не работает в обоих направлениях… итак, мы делаем это … из строки 98 в строку 2:
от 98 до 2 РАБОТАЕТ (2) 100 = 102, тогда 102-(98) = расстояние в 4
с 96 по 98 ОШИБКА (96) 100 = 196, тогда 196-(98) = расстояние 98 (правильно равно 2)
Как вы можете видеть, я не могу просто сказать, является ли start < end или start> end, поскольку числовой цикл все портит. Мне нужно каким-то образом определять, когда «Пересекается линия»…
После предложений Джонатана я понял, что отображение клиента и закулисье не обязательно должны совпадать. Я изменил движок, чтобы было 2 шестнадцатеричных значения… первое — это фактическая позиция, подобная 98,2 0,0 2,1. Другой — это буквальная позиция из порта просмотра.
Выглядит так:
Actual: 96 97 98 99 00 01 02 03 04 <= display in client amp; reference hexGridModel
Literal: -4 -3 -2 -1 00 01 02 03 04 <= use to calculate buffer position updates from camera
Литерал просто с точки зрения «отображения». Позже мне понадобится исправление, чтобы посмотреть, пройдем ли мы -100 или 100, но на данный момент эта проблема решена, а размеры карты динамические, поэтому над этим нужно будет поработать позже
Теперь я просто использовал это для любого случая.
var x, y = 0
x = this.buffer.coords.current.x - this.buffer.coords.last.x;
y = this.buffer.coords.current.y - this.buffer.coords.last.y;
Ответ №1:
Я бы сказал, что это на самом деле невозможно без дополнительной информации, чем вы нам предоставили. Возьмем пример перехода от 2 к 98. Вы не сможете определить, перешел ли пользователь из 2 -> 1 -> 0 -> 99 -> 98
или 2 -> 3 -> 4 -> ... -> 97 -> 98
.
Итак, ключом к возможности определить это является знание направления, в котором движется игрок или объект.
Если вы знаете это, вы можете сказать (предполагая, что 0 находится на левой границе сетки, а 99 — на правой границе сетки):
if ((direction == LEFT amp;amp; new_pos > old_pos) || (direction == RIGHT amp;amp; new_pos < old_pos) {
// The "line" has been crossed.
} else {
// The "line" was not crossed.
}
Если вам также нужно знать пройденное расстояние, вы можете разбить его следующим образом:
GRID_SIZE = 100
if (direction == LEFT amp;amp; new_pos > old_pos) {
distance = (GRID_SIZE - new_pos) old_pos;
} else if (direction == RIGHT amp;amp; new_pos < old_pos) {
distance = (GRID_SIZE - old_pos) new_pos;
} else {
distance = abs(new_pos - old_pos)
}
Комментарии:
1. ДА… это была еще одна идея, но проблема в том, что камера для игры копирует данные из буфера для отображения. итак, на экране отображается camera.position camera.pan. Таким образом, при активном панорамировании вычисление истинного направления кажется сложным. если они перемещаются на 100 пикселей влево, то в том же «панорамировании» они перемещаются на 50 пикселей вправо. Мне нужно было бы добавить индикатор, поскольку mouse.click.position не был бы надежным…
2. Я думаю, что лучше всего было бы каждый раз запускать событие «перетаскивания» во время панорамирования. Я должен проверить вашу текущую координату мыши по сравнению с последним запуском (миллисекунды назад) и определить направление… кажется, это лучший способ?
3. Вы могли бы это сделать. Вы также можете попытаться определить, где находятся края сетки по сравнению с краями окна просмотра. Если левый край сетки больше левого края окна просмотра, то «линия» была пересечена. Аналогично, если правый край сетки меньше правого края окна просмотра, то «линия» была пересечена.
Ответ №2:
Примечание: Я опубликовал следующее до того, как увидел обновление вопроса. Это то, что, как я догадался, вы могли иметь в виду в своем первоначальном вопросе. Может быть, это все равно будет как-то полезно.
Я не совсем понимаю формулировку требования, поэтому я предполагаю, что это «Найти кратчайшее расстояние между двумя позициями, позволяющее переносить границу 99/0, если она короче».
Эта функция возвращает объект с тремя свойствами: расстоянием, направлением и окружностью (true / false). И я вставил toString()
для удобства тестирования.
function shortestDistance(startPosition, endPosition) {
var difference = startPosition > endPosition
? startPosition - endPosition
: endPosition - startPosition,
wrapped = difference > 50;
return {
distance : wrapped ? 100 - difference : difference,
direction : (startPosition < endPosition
? (wrapped ? "left" : "right")
: (wrapped ? "right" : "left")),
wrappedAround : wrapped,
toString : function() {
return (
this.distance === 0
? "Didn't move"
: "Travelled " this.distance
" to the " this.direction ", and "
(this.wrappedAround ? "did" : "didn't")
" wrap around.");
}
};
}
var result = shortestDistance(2,98);
alert(result.distance); // 4
alert(result.direction); // "left"
alert(result.wrappedAround); // true
alert(shortestDistance(2,98));
// Travelled 4 to the left, and did wrap around.
alert(shortestDistance(98,2));
// Travelled 4 to the right, and did wrap around.
alert(shortestDistance(96,98));
// Travelled 2 to the right, and didn't wrap around.
alert(shortestDistance(98,96));
// Travelled 2 to the left, and didn't wrap around.
alert(shortestDistance(43, 43));
// Didn't move
alert(shortestDistance(1, 50));
// Travelled 49 to the right, and didn't wrap around.
alert(shortestDistance(1, 51));
// Travelled 50 to the right, and didn't wrap around.
alert(shortestDistance(1, 52));
// Travelled 49 to the left, and did wrap around.
alert(shortestDistance(50, 1));
// Travelled 49 to the left, and didn't wrap around.
alert(shortestDistance(51, 1));
// Travelled 50 to the left, and didn't wrap around.
alert(shortestDistance(52, 1));
// Travelled 49 to the right, and did wrap around.