Canvas 30度等距网格鼠标坐标转瓦片坐标问题求解
30度等距网格鼠标悬停瓦片识别方案
你的坐标转换问题不需要试错调参,直接对现有正向投影公式做逆矩阵求解,就能得到100%匹配的反向转换逻辑,完全适配你保留√3系数的30度视角要求。
实现原理
你当前使用的正向笛卡尔坐标转等距画布坐标公式是线性变换,对应二元一次方程组:
设原始平面网格坐标为
(cartX, cartY),投影后的画布坐标为(isoX, isoY)isoX = (cartX - cartY) * (√3 / 2) + canvasOffset isoY = (cartX + cartY) / 2
直接解这个方程组求cartX和cartY,就能得到精确的反向转换公式,不需要手动猜系数位置:
cartX = (isoX - canvasOffset) / √3 + isoY cartY = isoY - (isoX - canvasOffset) / √3
可直接使用的代码
1. 基础坐标转换函数
和你现有carToIso函数完全对称,无精度损失:
// 等距画布坐标转原始平面网格坐标(连续像素值) function isoToCar(isoX, isoY) { const cos30 = Math.sqrt(3) / 2; // 和正向投影的角度参数完全一致 const xDelta = isoX - canvasOffset; const cartX = xDelta / (2 * cos30) + isoY; const cartY = isoY - xDelta / (2 * cos30); return [cartX, cartY]; }
2. 鼠标悬停瓦片索引计算
注意用Math.floor做索引取整,不要用Math.round,避免半格位置跳变导致识别偏移:
// 输入canvas内鼠标坐标,返回悬停的瓦片[列索引, 行索引] function getHoverTile(mouseX, mouseY) { const [cartX, cartY] = isoToCar(mouseX, mouseY); // 超出网格范围时返回的索引会<0或>=网格行列数,可自行做边界过滤 const col = Math.floor(cartX / tileSize); const row = Math.floor(cartY / tileSize); return [col, row]; }
注意事项
- 该方案完全保留你原有√3系数的投影逻辑,和30度制作的美术资源不会出现对齐偏差
- 如果需要做边缘容错(比如鼠标在瓦片交界位置时避免频繁跳变),可以在计算索引前给
cartX/cartY加固定偏移,偏移值根据美术资源的实际碰撞区域调整即可 - 验证方法:将任意
carToIso(x,y)的输出传入isoToCar,得到的结果和原始输入(x,y)的误差仅来自JS浮点数计算,可忽略
内容的提问来源于stack exchange,提问作者Gerard
相关产品推荐
相关产品推荐

