Разрешение холста мешает смещению для обнаружения столкновения мыши с плитками - Isometric Engine - PullRequest
0 голосов
/ 15 сентября 2018

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

Как видите, мышь правильно подобрана как находящаяся на плитке. Регистрируемые числа - это значение X, Y мыши по отношению к контексту.

Вот пример изображения обнаружения столкновения с разрешением 1024 x 672, со смещением X Y 512 x 32.

enter image description here

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

Вот код, который устанавливает холст

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: Я был бы рад предоставить полный исходный код, если кто-то заинтересован и готов помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...