画布分辨率混淆了用于平铺鼠标碰撞检测的偏移量-Isometric Engine

时间:2018-09-15 18:41:37

标签: javascript html5 canvas

TLDR:我创建了一个等轴测图引擎。当我更改画布的尺寸时,鼠标的碰撞检测不会以适当的偏移量更新。 -偏移量不是常数,因此我认为情况并非如此。还请注意,CSS和JS中的尺寸均已更改。

我正在使用HTML5画布和香草JS开发基于等距的游戏。我最初遵循的是在youtube上找到的教程,然后退出该教程,开始自己尝试编写代码。

我目前面临的问题如下:

我的图块大小为128 x 64像素,最初我认为画布的分辨率大小并不重要,所以在我开始的时候,我开始使用1088 x 650之类的分辨率。我通过将画布的上下文居中并从0,0开始绘制来设置地图

这意味着我必须将上下文转换为canvas.width / 2。我也将其翻译下来,以便在屏幕顶部创建一些可用空间。这是在y处以tilewidth / 2

转换的

后来,我意识到地图越大(在屏幕上绘制的图块),绘制的速度就越慢。因此,我设置了摄像机剔除,以便仅绘制适合屏幕的内容。这是当我意识到我应该将画布的大小调整为瓦片尺寸的一个因素时,因此我将画布的宽度和高度更改为1024、672。起初我没有注意到任何问题。

我今天开始注意到的是,当我将鼠标悬停在其中一个图块上时,鼠标位置似乎会根据两种分辨率之间的差异而偏移。因此,注意到鼠标距其应为x:-64,y:22。因此,鼠标和图块之间的冲突检测远非准确。我对此感到困惑,因为我用来将摄影机平移到起始位置的X和Y偏移量没有使用常量,因此它应该可以很好地适应新的分辨率。

这是鼠标和图块之间的碰撞检测的示例图像,分辨率为1088 x 650,偏移为544 x 32:

enter image description here

如您所见,鼠标已正确放置在图块中。记录的数字是鼠标相对于上下文的X,Y值。

这是碰撞检测的示例图像,分辨率为1024 x 672,XY偏移为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数组中。然后,我遍历temp数组,并检查鼠标坐标是否在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;
};

每次移动图块时,都会清除temp数组,然后使用新坐标重新填充它们。您可以在视口对象中看到这一点,但是问题仍然存在,而没有移动地图。

如果我将所有偏移量都设置为非常数,为什么不能不更改检测鼠标位置的位置而不能更改画布的尺寸?

这里有很多信息,我也没有提供很多代码,因为我不确定是否有必要。请花一点时间对此进行回顾,然后再回覆我。我真的很感谢任何建议。

PS:如果有人对此感兴趣并愿意提供帮助,我将很乐意提供完整的源代码。

0 个答案:

没有答案