TLDR: я создал изометрический движок плиток. Когда я изменяю размеры холста, обнаружение столкновения мыши не обновляется с правильным смещением. - смещения не являются постоянными, и поэтому я не считаю, что это должно быть так. Также обратите внимание, что размеры были изменены как в CSS, так и в JS.
Я работаю над игрой на изометрической основе с использованием HTML5 canvas и vanilla JS. Первоначально я следовал учебному пособию, которое нашел на youtube, а затем расстался с ним и начал отрабатывать код самостоятельно.
Проблема, с которой я сейчас сталкиваюсь, такова:
Размеры моих плиток - 128 x 64 пикселей, изначально я не думал, что это имеет значение, какой размер я выбрал для разрешения моего холста, поэтому, начав, я начал с чего-то вроде 1088 x 650. В таком случае, Я настраиваю карту, центрируя контекст холста и рисуя от 0,0
Это означает, что мне пришлось перевести контекст в canvas.width / 2. Я также перевел это вниз, чтобы создать свободное место в верхней части экрана. Это было переведено на y на плитке / 2
Позже я понял, что чем больше карта (плитки, нарисованные на экране), тем медленнее она рисовалась. Поэтому я настроил отбор камеры так, чтобы рисовать было только то, что помещалось на экране. Именно тогда я понял, что должен изменить размер холста, чтобы он учитывал размеры плитки, поэтому я изменил ширину и высоту холста на 1024, 672. Сначала я не заметил никаких проблем с этим.
Сегодня я начал замечать, что при наведении курсора на одну из плиток положение мыши кажется смещенным в зависимости от разницы между двумя разрешениями. Итак, мышь замечена как x: -64, y: 22 от того, что она должна быть. Из-за этого обнаружение столкновения между мышью и плитками далеко от точного. Я смущен этим, потому что смещение по осям X и Y, которое я использовал для перевода камеры в исходное положение, не использует константы, и поэтому он должен просто приспособиться к новому разрешению.
Вот пример изображения обнаружения столкновения между мышью и плиткой с разрешением 1088 x 650 и смещением 544 x 32:
![enter image description here](https://i.stack.imgur.com/0sVg1.gif)
Как видите, мышь правильно подобрана как находящаяся на плитке. Регистрируемые числа - это значение X, Y мыши по отношению к контексту.
Вот пример изображения обнаружения столкновения с разрешением 1024 x 672, со смещением X Y 512 x 32.
![enter image description here](https://i.stack.imgur.com/m6YKs.gif)
Здесь вы можете видеть, что мышь подобрана как находящаяся слева от плитки, и что высота плитки кажется меньшей, чем она была до изменения размеров, есть область сверху и нижняя часть плитки, которая не подхватывает мышь.
Вот код, который устанавливает холст
stage.canvas = document.createElement("canvas");
var context = stage.canvas.getContext("2d");
var width = stage.canvas.width = 1088;
var height = stage.canvas.height = 650;
stage.handle.appendChild(stage.canvas);
stage.context = context;
tileWidth = 128;
tileHeight = 64;
var mapW = 5;
var mapH = 5;
var offsetX = width/2;
var offsetY = tileHeight/2;
stage.context.translate(offsetX, offsetY);
Существует объект области просмотра, который управляет элементами управления камерой:
stage.viewport = {
incx: 64,
incy: 32,
offsetx: 0,
offsety: 0,
currentOffset: [0,0],
updateUP: function()
{
temp = [];
stage.context.translate(0, this.incy);
this.offsety += this.incy;
this.currentOffset = [this.currentOffset[0], -this.offsety]
stage.context.clearRect((-512 - this.offsetx),(-32 - this.offsety), stage.canvas.width, stage.canvas.height)
stage.context.beginPath();
stage.initiateMap();
reDrawMap(0, 0);
},
updateDOWN: function()
{
temp = [];
stage.context.translate(0, -this.incy);
this.offsety -= this.incy;
this.currentOffset = [this.currentOffset[0], -this.offsety]
stage.context.clearRect((-512 - this.offsetx),(-32 - this.offsety), stage.canvas.width, stage.canvas.height)
stage.context.beginPath();
stage.initiateMap();
reDrawMap(0, 0);
},
updateLEFT: function()
{
temp = [];
stage.context.translate(-this.incx, 0);
this.offsetx -= this.incx;
this.currentOffset = [-this.offsetx, this.currentOffset[1]]
stage.context.clearRect((-512 - this.offsetx),(-32 - this.offsety), stage.canvas.width, stage.canvas.height)
stage.context.beginPath();
stage.initiateMap();
reDrawMap(0, 0);
},
updateRIGHT: function()
{
temp = [];
stage.context.translate(this.incx, 0);
this.offsetx += this.incx;
this.currentOffset = [-this.offsetx, this.currentOffset[1]]
stage.context.clearRect((-512 - this.offsetx),(-32 - this.offsety), stage.canvas.width, stage.canvas.height)
stage.context.beginPath();
stage.initiateMap();
reDrawMap(0, 0);
},
Это не должно быть важно, потому что, даже если камера не перемещается, проблема сохраняется, объект выше относится только к движениям камеры с помощью клавиш со стрелками на клавиатуре. Я подумал, что в любом случае это может быть полезно, поскольку я не знаю, в чем истинная проблема.
Вот функция, которая определяет, где находится мышь:
function getMouseCoords(canvas, evt){
console.log(offsetX, offsetY)
var rect = canvas.getBoundingClientRect();
return {
x: (evt.clientX - rect.left) - (offsetX),
y: (evt.clientY - rect.top) - (offsetY)
};
}
Теперь, что касается выделения плитки. Когда каждая плитка размещается на карте, ее координаты (все 4 точки) сохраняются в объекте, который затем помещается во временный массив. Затем я перебираю массив временных переменных и проверяю, находятся ли координаты мыши внутри координат плитки в точке temp [n]. Это выглядит так:
var polygon = [ [box.A_top[0], box.A_top[1]],[box.B_right[0], box.B_right[1]], [box.C_bottom[0], box.C_bottom[1]], [box.D_left[0], box.D_left[1]]];
//if the mouse is inside the polygon
if(inside([x, y], polygon))
{
if(stage.drawMode){
//highlight this tile
drawTile(box.x, box.y, "red");
}
}
А вот функция inside ():
function inside(point, vs)
{
var x = point[0], y = point[1];
var inside = false;
for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
var xi = vs[i][0], yi = vs[i][1];
var xj = vs[j][0], yj = vs[j][1];
var intersect = ((yi > y) != (yj > y))
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
};
Каждый раз, когда плитки перемещаются, временный массив очищается, а затем заполняется новыми координатами. Вы можете видеть это в объекте области просмотра, но опять проблема остается без перемещения карты.
Почему я не могу изменить размеры холста, не изменив местоположение мыши, если у меня все смещения не постоянны?
Здесь много информации и много кода, который я не предоставил, потому что я не был уверен, что это необходимо. Пожалуйста, найдите время, чтобы рассмотреть это и вернуться ко мне. Я действительно ценю любые советы.
PS: Я был бы рад предоставить полный исходный код, если кто-то заинтересован и готов помочь.