/** * wuxing-sandbox-helpers/hitdetect.js * 五角星点击检测工具(纯函数,无状态) */ var DIM_KEYS = ['body', 'mind', 'wisdom', 'action', 'wealth'] /** * 射线法(Ray Casting)判断点是否在任意多边形内 * @param {number} x - 点的 x 坐标 * @param {number} y - 点的 y 坐标 * @param {Array<{x:number,y:number}>} polygon - 多边形顶点数组 * @returns {boolean} */ export function pointInPolygon(x, y, polygon) { var inside = false var n = polygon.length for (var i = 0, j = n - 1; i < n; j = i++) { var xi = polygon[i].x var yi = polygon[i].y var xj = polygon[j].x var yj = polygon[j].y if ((yi > y) !== (yj > y) && x < (xj - xi) * (y - yi) / (yj - yi) + xi) { inside = !inside } } return inside } /** * 计算指定星臂的多边形顶点 * @param {number} armIndex - 星臂索引 0~4 (body/mind/wisdom/action/wealth) * @param {number} cx - 中心 x * @param {number} cy - 中心 y * @param {{outer:Array,inner:Array}} vertices - calcStarVertices 返回值 * @returns {Array<{x:number,y:number}>} */ export function calcArmPolygon(armIndex, cx, cy, vertices) { var outer = vertices.outer var inner = vertices.inner var outerIdx = (armIndex + 4) % 5 var iBefore = (armIndex + 3) % 5 var iAfter = (armIndex + 4) % 5 return [ { x: cx, y: cy }, inner[iBefore], outer[outerIdx], inner[iAfter] ] } /** * 检测点击位置命中哪个星臂 * @param {number} relX - Canvas 相对 x 坐标 * @param {number} relY - Canvas 相对 y 坐标 * @param {number} cx - 中心 x * @param {number} cy - 中心 y * @param {number} outerR - 外半径 * @param {Function} calcVertices - calcStarVertices 函数引用 * @returns {number} 命中星臂索引 0~4,-1 表示未命中 */ export function detectHitArm(relX, relY, cx, cy, outerR, calcVertices) { var vertices = calcVertices(cx, cy, outerR) for (var i = 0; i < 5; i++) { var polygon = calcArmPolygon(i, cx, cy, vertices) if (pointInPolygon(relX, relY, polygon)) { return i } } return -1 } /** * 星臂索引 → 维度 key 映射 * @param {number} armIndex * @returns {string} 'body'|'mind'|'wisdom'|'action'|'wealth' */ export function armIndexToDomain(armIndex) { return DIM_KEYS[armIndex] || '' }