如何实现等轴测六边形瓦片地图?瓦片定位与点击检测求助
等轴测六边形瓦片地图的点击检测与瓦片定位实现
问题背景
我想要创建一个使用六边形而非正方形的等轴测瓦片地图,示例如下:
直接使用IsometricTileMapComponent搭配六边形瓦片会导致瓦片重叠错误,因此需要继承该组件并重写核心方法。目前已实现瓦片渲染位置计算的方法,但卡在了点击检测对应的getBlock方法实现上:
/// 获取等轴测位置[p]对应的瓦片 /// 用于处理点击或悬停事件,是[getBlockCenterPosition]的逆运算 Block getBlock(Vector2 p) { // 如何实现? } /// 获取瓦片(i,j)在等轴测空间中的渲染位置 /// 不包含PositionComponent的(x,y)偏移,假设瓦片精灵为矩形 /// 是[getBlockRenderedAt]的逆运算 Vector2 getBlockRenderPositionInts(int i, int j) { // 已实现的逻辑,确认可用 return Vector2((i - j) * surfaceSize.x * 0.75, (i + j) * surfaceSize.y / 2); }
getBlock方法实现思路与代码
要完成逆运算,需将屏幕点击的等轴测坐标p转换为瓦片网格坐标(i,j),核心基于六边形网格的坐标转换逻辑:
完整实现代码
Block getBlock(Vector2 p) { // 1. 归一化坐标,消除瓦片尺寸对计算的影响 final tileWidthUnit = surfaceSize.x * 0.75; final tileHeightUnit = surfaceSize.y * 0.5; final normalizedX = p.x / tileWidthUnit; final normalizedY = p.y / tileHeightUnit; // 2. 计算网格坐标的浮点近似值 var i = (normalizedX + normalizedY) / 2; var j = (normalizedY - normalizedX) / 2; // 3. 六边形边界修正,判断点击点实际落入的瓦片 final fracI = i - i.floor(); final fracJ = j - j.floor(); if (fracI + fracJ > 1.0) { i = i.ceilToDouble(); j = j.ceilToDouble(); } else { i = i.floorToDouble(); j = j.floorToDouble(); } // 转换为整数索引,返回对应瓦片(需自行处理地图边界越界情况) final intI = i.toInt(); final intJ = j.toInt(); return mapData.getBlock(intI, intJ); }
逻辑说明
- 坐标归一化:把点击坐标转换为相对瓦片单元的比例值,让计算不受瓦片实际尺寸影响,只关注网格相对位置;
- 近似坐标计算:完全对应
getBlockRenderPositionInts的逆运算,将渲染坐标转换为网格坐标的浮点近似值; - 六边形边界修正:等轴测六边形的有效点击区域不是矩形,通过判断坐标小数部分的和,修正近似坐标,确保点击点匹配到正确的六边形瓦片。
内容的提问来源于stack exchange,提问作者BeMain
相关产品推荐
相关产品推荐

