You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现等轴测六边形瓦片地图?瓦片定位与点击检测求助

等轴测六边形瓦片地图的点击检测与瓦片定位实现

问题背景

我想要创建一个使用六边形而非正方形的等轴测瓦片地图,示例如下:
等轴测六边形瓦片地图示例

直接使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:13:06