gpt4 book ai didi

javascript - 使用 Canvas 的等距瓷砖 map (带点击检测)

转载 作者:行者123 更新时间:2023-11-27 22:33:18 25 4
gpt4 key购买 nike

我目前正在开发一款游戏,需要一张由各种图 block 图像组成的 map 。我设法使它们正确显示(参见第二张图片),但我现在不确定如何从鼠标位置计算单击的图 block 。

是否有用于此目的的现有库?

另请注意,平铺图像并不是完美地“面向 Angular 落相机”绘制的,而是稍微顺时针旋转。

enter image description here enter image description here

最佳答案

等距变换

定义投影

等距显示与标准显示相同,唯一改变的是 x 和 y 轴的方向。通常,x 轴定义为 (1,0) 横向 1 个单位、向下 0 个单位,y 轴定义为 (0,1) 横向 0 个单位、向下 1 个单位。对于等轴测(严格来说,您的图像是二轴投影),您将得到类似 x 轴 (0.5,1) 和 y 轴 (-1,0.5) 的内容

矩阵

由此,您可以创建一个具有 6 个值的渲染矩阵,两个值分别用于两个轴,两个用于原点,我现在将忽略它(原点),仅使用 4 作为轴,并假设原点始终为在 0,0

var dimetricMatrix = [0.5,1.0,-1,0.5]; // x and y axis

矩阵变换

从中,您可以在显示屏上获取与给定等距坐标相匹配的点。假设这些 block 的大小为 200 x 200 像素,并且您通过 block x 和 y 来寻址每个 block 。因此,图像底部的 block 位于 x = 2y = 1(第一个顶部 block 是 x = 0y = 0)

使用矩阵我们可以得到 block 的像素位置

var blockW = 200;
var blockH = 200;
var locX = 2;
var locY = 1;

function getLoc(x,y){
var xx,yy; // intermediate results
var m = dimetricMatrix; // short cut to make code readable
x *= blockW; // scale up
y *= blockH;
// now move along the projection x axis
xx = x * m[0];
yy = x * m[1];
// then add the distance along the y axis
xx += y * m[2];
yy += y * m[3];

return {x : xx, y : yy};
}

在继续之前,您可以看到我已按 block 大小缩放了 x 和 y。我们可以简化上面的代码,将尺度200,200包含在矩阵中

var xAxis = [0.5, 1.0];
var yAxis = [-1, 0.5];
var blockW = 200;
var blockH = 200;
// now create the matrix and scale the x and y axis
var dimetricMatrix = [
xAxis[0] * blockW,
xAxis[1] * blockW,
yAxis[0] * blockH,
yAxis[1] * blockH,

]; // x and y axis

矩阵保存 x 轴和 y 轴的比例,以便 x 轴的两个数字告诉我们变换单元的方向和长度。

简化功能

并重做getLoc函数以提高速度和效率

function transformPoint(point,matrix,result){
if(result === undefined){
result = {};
}
// now move along the projection x axis
result.x = point.x * matrix[0] + point.y * matrix[2];
result.y = point.x * matrix[1] + point.y * matrix[3];
return result;
}

因此传递一个点并返回一个变换后的点。结果参数允许您传递现有点,并且如果您经常这样做,则可以节省分配新点的麻烦。

var point = {x : 2, y : 1};
var screen = transformPoint(point,dimetricMatrix);
// result is the screen location of the block

// next time
screen = transformPoint(point,dimetricMatrix,screen); // pass the screen obj
// to avoid those too
// GC hits that kill
// game frame rates

矩阵求逆

所有这些都很方便,但您需要与我们刚刚所做的相反的操作。幸运的是,矩阵的工作方式允许我们通过反转矩阵来反转该过程。

function invertMatrix(matrix){
var m = matrix; // shortcut to make code readable
var rm = [0,0,0,0]; // resulting matrix
// get the cross product of the x and y axis. It is the area of the rectangle made by the
// two axis
var cross = m[0] * m[3] - m[1] * m[2]; // I call it the cross but most will call
// it the determinate (I think that cross
// product is more suited to geometry while
// determinate is for maths geeks)
rm[0] = m[3] / cross; // invert both axis and unscale (if cross is 1 then nothing)
rm[1] = -m[1] / cross;
rm[2] = -m[2] / cross;
rm[3] = m[0] / cross;
return rm;
}

现在我们可以反转矩阵

var dimetricMatrixInv = invertMatrix(dimetricMatrix); // get the invers

现在我们有了逆矩阵,我们可以使用变换函数将屏幕位置转换为 block 位置

var screen = {x : 100, y : 200};
var blockLoc = transformPoint(screen, dimetricMatrixInv );
// result is the location of the block

渲染矩阵

为了实现一点神奇,2D Canvas 也可以使用变换矩阵 dimetricMatrix,但您需要添加原点。

var m = dimetricMatrix;
ctx.setTransform(m[0], m[1], m[2], m[3], 0, 0); // assume origin at 0,0

现在您可以使用以下命令在 block 周围绘制一个框

ctx.strokeRect(2,1,1,1); // 3rd by 2nd block 1 by 1 block wide.

起源

我在上面的所有内容中都省略了起源,我将把它留给你去查找,因为网上有数万亿个关于矩阵的页面,因为所有 2D 和 3D 渲染都使用它们,并且深入了解它们非常重要如果您想进入计算机可视化领域。

关于javascript - 使用 Canvas 的等距瓷砖 map (带点击检测),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39367005/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com