我目前正在开发一款游戏,需要一张由各种图块组成的地图。我设法让它们正确显示(见第二张图片)但我现在不确定如何从鼠标位置计算点击的图块。
是否有用于此目的的现有库?
请注意,瓷砖图像不能完美地绘制为“朝向相机的角落”,它们会顺时针轻微旋转。
答案 0 :(得分:1)
定义投影
等距显示与标准显示相同,唯一改变的是x和y轴的方向。通常,x轴定义为(1,0)一个单位横向和零向下,y轴是(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
矩阵转换
由此可以在显示屏上获得与给定等距坐标匹配的点。假设块是200乘200像素,并且您通过块x和y对每个块进行寻址。因此,图片底部的块位于x = 2
和y = 1
(第一个顶部块为x = 0
,y = 0
)
使用矩阵我们可以得到块的像素位置
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};
}
Befoer我继续前进你可以看到我按块大小缩放了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
现在我们有逆矩阵,我们可以使用变换函数从屏幕位置转换为块位置
var screen = {x : 100, y : 200};
var blockLoc = transformPoint(screen, dimetricMatrixInv );
// result is the location of the block
用于渲染的矩阵
对于一些魔术,2D画布也可以使用变换矩阵dimetricMatrix
,但是你需要添加原点。
var m = dimetricMatrix;
ctx.setTransform(m[0], m[1], m[2], m[3], 0, 0); // assume origin at 0,0
现在,您可以使用
在块周围绘制一个框ctx.strokeRect(2,1,1,1); // 3rd by 2nd block 1 by 1 block wide.
原点
我遗漏了上述所有内容,我将把这一点留给你找到,因为所有2D和3D渲染都使用它们并且对它们有深入了解,因此在线有关于矩阵的数万亿页如果你想进入计算机可视化。