local SLG_Utility = {} local private = {} local tempSet = {} local gridCount local gridSize local uiWidth local uiHeight local uiHalfWidth --二分之一格子UI宽 local uiQuarterWidth --四分之一格子UI宽 local uiHalfHeight local uiQuarterHeight local uiThreeQuarterHeight --四分之一格子UI高 --gridPerCount:格子数量 gridPerCount*gridPerCount --widthUI、heightUI:UI格子的长宽 function SLG_Utility.InitSlgMap(gridPerCount, widthUI, heightUI) gridSize = gridPerCount gridCount = gridPerCount * gridPerCount uiWidth = widthUI uiHeight = heightUI uiHalfWidth = uiWidth / 2 uiQuarterWidth = uiWidth / 4 uiHalfHeight = uiHeight / 2 uiQuarterHeight = uiHeight / 4 uiThreeQuarterHeight = uiQuarterHeight * 3 end --获取拖拽限制矩形的四个格子坐标索引 function SLG_Utility.GetDragLimitRectIndex(dragLimitMiddleIndex, horizontalCount, verticalCount) local hCount = math.ceil(horizontalCount / 2) local vCount = math.ceil(verticalCount / 2) local middleTopIndex = SLG_Utility.VerticalFindGridIndex(dragLimitMiddleIndex, -vCount) local leftTopIndex = SLG_Utility.HorizontalFindGridIndex(middleTopIndex, -hCount) local leftBottomIndex = SLG_Utility.VerticalFindGridIndex(leftTopIndex, verticalCount) local rightTopIndex = SLG_Utility.HorizontalFindGridIndex(leftTopIndex, horizontalCount) local rightBottomIndex = SLG_Utility.HorizontalFindGridIndex(leftBottomIndex, horizontalCount) return leftTopIndex, leftBottomIndex, rightTopIndex, rightBottomIndex end function SLG_Utility.PositionToIndex(x, y) return y * gridSize + x + 1 end function SLG_Utility.IndexToPosition(index) if index == 0 then return 0, 0 end return (index - 1) % gridSize, math.floor((index - 1) / gridSize) end --通过格子尺寸和坐标规律,映射UI坐标 function SLG_Utility.PositionToUIPosition(x, y) return (-1 - y) * uiHalfWidth + uiQuarterWidth * x, (-1 - y) * uiHalfHeight - uiThreeQuarterHeight * x end function SLG_Utility.PositionToUnitUIPosition(x, y) return (-1 - y) * 0.5 + 0.25 * x, (-1 - y) * 0.5 - 0.75 * x end function SLG_Utility.UnitUIPositionToPosition(x, y) return math.ceil(x - y), math.ceil(-(-1 - (x - 0.25 * (x - y)) / -0.5)) end --从centerIndex为中心收集horizontalCount*verticalCount个格子,不考虑边界问题 function SLG_Utility.CollectRectGrids(centerIndex, horizontalMaxNum, verticalMaxNum, container) local horizontalCount = math.ceil(horizontalMaxNum / 2) local verticalCount = math.ceil(verticalMaxNum / 2) local middleTopIndex = SLG_Utility.VerticalFindGridIndex(centerIndex, -verticalCount) local leftTopIndex = SLG_Utility.HorizontalFindGridIndex(middleTopIndex, -horizontalCount) table.clear(tempSet) SLG_Utility.VerticalFindGridIndex(leftTopIndex, verticalMaxNum, tempSet) for index, _ in pairs(tempSet) do container[index] = true SLG_Utility.HorizontalFindGridIndex(index, horizontalMaxNum, container) end end --水平方向找count个格子,不考虑边界问题 --count为正数朝右找,负数则朝左找 function SLG_Utility.HorizontalFindGridIndex(startIndex, count, container) local x, y = SLG_Utility.IndexToPosition(startIndex) local xValue local yValue = y if count > 0 then xValue = x - 1 --向右查找 for j = 1, count do if j % 3 == 1 or j % 3 == 2 then xValue = xValue + 1 elseif j % 3 == 0 then xValue = xValue end if container then container[SLG_Utility.PositionToIndex(xValue, yValue - j + 1)] = true end end return SLG_Utility.PositionToIndex(xValue, yValue - count + 1) else xValue = x + 1 --向左查找 count = -count for j = 1, count do if j % 3 == 1 or j % 3 == 2 then xValue = xValue - 1 elseif j % 3 == 0 then xValue = xValue end if container then container[SLG_Utility.PositionToIndex(xValue, yValue + j - 1)] = true end end return SLG_Utility.PositionToIndex(xValue, yValue + count - 1) end end --垂直方向找count个格子,不考虑边界问题 --count为正数朝下找,负数则朝上找 function SLG_Utility.VerticalFindGridIndex(startIndex, count, container) local x, y = SLG_Utility.IndexToPosition(startIndex) local yValue = y local xValue if count > 0 then xValue = x - 1 for i = 1, count do if i % 3 == 2 or i % 3 == 1 then xValue = xValue + 1 else xValue = xValue end --前两个值不变,之后每三个递增一次 if i <= 2 then yValue = yValue elseif i % 3 == 0 then yValue = yValue + 1 end if container then container[SLG_Utility.PositionToIndex(xValue, yValue)] = true end end else xValue = x + 1 count = -count for i = 1, count do if i % 3 == 2 or i % 3 == 1 then xValue = xValue - 1 else xValue = xValue end if i <= 2 then yValue = yValue elseif i % 3 == 0 then yValue = yValue - 1 end if container then container[SLG_Utility.PositionToIndex(xValue, yValue)] = true end end end return SLG_Utility.PositionToIndex(xValue, yValue) end --根据中心索引找到视野内的格子,将格子索引收集到container中 function SLG_Utility.CollectGridsByCenterIndex(centerIndex, horizontalMaxNum, verticalMaxNum, container) if centerIndex <= 0 or centerIndex > gridCount then return false end table.clear(container) SLG_Utility.CollectRectGrids(centerIndex, horizontalMaxNum, verticalMaxNum, container) return true end --根据移动偏移量和当前索引值计算出下一个中心索引值 function SLG_Utility.GetNextCenterIndex(currentIndex, moveX, moveY) local showX, showY = SLG_Utility.IndexToPosition(currentIndex) local uiPositionX, uiPositionY = SLG_Utility.PositionToUIPosition(showX, showY) local deltaX, deltaY = moveX - uiPositionX, moveY - uiPositionY local nextX, nextY = showX, showY if deltaX > 0 then local step = math.ceil(deltaX / uiHalfWidth) - 1 if step > 0 then nextY = showY - step if step == 1 then nextX = nextX + 1 nextX, nextY = private.CalculationVertical(uiThreeQuarterHeight, deltaY, nextX, nextY) elseif step == 2 then nextX = nextX + 1 nextX, nextY = private.CalculationVertical(uiQuarterHeight, deltaY, nextX, nextY) elseif step >= 3 then --这里限制了最大步长 nextX = nextX + 2 nextX, nextY = private.CalculationVertical(uiHalfHeight, deltaY, nextX, nextY) end else nextX, nextY = private.CalculationVertical(uiHalfHeight, deltaY, nextX, nextY) end elseif deltaX < 0 then local step = math.floor(deltaX / uiHalfWidth) + 1 if step < 0 then nextY = showY - step if step == -1 then nextX = nextX - 1 nextX, nextY = private.CalculationVertical(uiQuarterHeight, deltaY, nextX, nextY) elseif step == -2 then nextX = nextX - 1 nextX, nextY = private.CalculationVertical(uiThreeQuarterHeight, deltaY, nextX, nextY) elseif step >= -3 then nextX = nextX - 2 nextX, nextY = private.CalculationVertical(uiHalfHeight, deltaY, nextX, nextY) end else nextX, nextY = private.CalculationVertical(uiHalfHeight, deltaY, nextX, nextY) end else nextX, nextY = private.CalculationVertical(uiHalfHeight, deltaY, nextX, nextY) end if nextX < 0 then nextX = 0 end if nextY < 0 then nextY = 0 end return SLG_Utility.PositionToIndex(nextX, nextY) end --(2,7) (3,7) (3,8) (4,8) (5,8) (5,9) (6,9) (7,9) (7,10) --对着格子中心垂直画线,根据垂直步长计算坐标 function private.CalculationVertical(startStep, moveY, x, y) moveY = -moveY if moveY > 0 then local step = moveY - startStep if step > 0 then local stepCount = math.ceil(step / uiHalfHeight) - 1 if stepCount == 1 then x = x + 1 elseif stepCount == 2 then x = x + 1 y = y + 1 elseif stepCount > 2 then --这里能这么写是因为前边处理了,一次拖拽最大步长不会超过3 x = x + 2 y = y + 1 end end elseif moveY < 0 then local step = moveY - startStep if step < 0 then local stepCount = math.floor(step / uiHalfHeight) + 1 if stepCount == -1 then x = x - 1 elseif stepCount == -2 then x = x - 1 y = y - 1 elseif stepCount < -2 then x = x - 2 y = y - 1 end end end if x > gridSize - 1 then x = gridSize - 1 end return x, y end function SLG_Utility.GetLinkedGridIndexes(gridIndex) local x, y = SLG_Utility.IndexToPosition(gridIndex) return gridIndex, SLG_Utility.PositionToIndex(x - 1, y), SLG_Utility.PositionToIndex(x - 1, y + 1), SLG_Utility.PositionToIndex(x, y - 1), SLG_Utility.PositionToIndex(x, y + 1), SLG_Utility.PositionToIndex(x + 1, y - 1), SLG_Utility.PositionToIndex(x + 1, y) end return SLG_Utility