hitdetect.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /**
  2. * wuxing-sandbox-helpers/hitdetect.js
  3. * 五角星点击检测工具(纯函数,无状态)
  4. */
  5. var DIM_KEYS = ['body', 'mind', 'wisdom', 'action', 'wealth']
  6. /**
  7. * 射线法(Ray Casting)判断点是否在任意多边形内
  8. * @param {number} x - 点的 x 坐标
  9. * @param {number} y - 点的 y 坐标
  10. * @param {Array<{x:number,y:number}>} polygon - 多边形顶点数组
  11. * @returns {boolean}
  12. */
  13. export function pointInPolygon(x, y, polygon) {
  14. var inside = false
  15. var n = polygon.length
  16. for (var i = 0, j = n - 1; i < n; j = i++) {
  17. var xi = polygon[i].x
  18. var yi = polygon[i].y
  19. var xj = polygon[j].x
  20. var yj = polygon[j].y
  21. if ((yi > y) !== (yj > y) && x < (xj - xi) * (y - yi) / (yj - yi) + xi) {
  22. inside = !inside
  23. }
  24. }
  25. return inside
  26. }
  27. /**
  28. * 计算指定星臂的多边形顶点
  29. * @param {number} armIndex - 星臂索引 0~4 (body/mind/wisdom/action/wealth)
  30. * @param {number} cx - 中心 x
  31. * @param {number} cy - 中心 y
  32. * @param {{outer:Array,inner:Array}} vertices - calcStarVertices 返回值
  33. * @returns {Array<{x:number,y:number}>}
  34. */
  35. export function calcArmPolygon(armIndex, cx, cy, vertices) {
  36. var outer = vertices.outer
  37. var inner = vertices.inner
  38. var outerIdx = (armIndex + 4) % 5
  39. var iBefore = (armIndex + 3) % 5
  40. var iAfter = (armIndex + 4) % 5
  41. return [
  42. { x: cx, y: cy },
  43. inner[iBefore],
  44. outer[outerIdx],
  45. inner[iAfter]
  46. ]
  47. }
  48. /**
  49. * 检测点击位置命中哪个星臂
  50. * @param {number} relX - Canvas 相对 x 坐标
  51. * @param {number} relY - Canvas 相对 y 坐标
  52. * @param {number} cx - 中心 x
  53. * @param {number} cy - 中心 y
  54. * @param {number} outerR - 外半径
  55. * @param {Function} calcVertices - calcStarVertices 函数引用
  56. * @returns {number} 命中星臂索引 0~4,-1 表示未命中
  57. */
  58. export function detectHitArm(relX, relY, cx, cy, outerR, calcVertices) {
  59. var vertices = calcVertices(cx, cy, outerR)
  60. for (var i = 0; i < 5; i++) {
  61. var polygon = calcArmPolygon(i, cx, cy, vertices)
  62. if (pointInPolygon(relX, relY, polygon)) {
  63. return i
  64. }
  65. }
  66. return -1
  67. }
  68. /**
  69. * 星臂索引 → 维度 key 映射
  70. * @param {number} armIndex
  71. * @returns {string} 'body'|'mind'|'wisdom'|'action'|'wealth'
  72. */
  73. export function armIndexToDomain(armIndex) {
  74. return DIM_KEYS[armIndex] || ''
  75. }