Добавлен MpW
Хочу сделать показ территории деревни молниями. это соединение геометрических фигур. Возникла проблема. Что это мой алгоритм криво работает
существует ли нормальный алгоритм поиска? могу конечно дать код, но без карты бесполезен.
код
function RightTopVertex takes integer n, real cx, real cy returns nothing
local real block = 32
local real x = cx
local real y = cy
local boolean b
loop
set b = (not IsPointInRegion(udg_Region[n],x+block,y))
if b then
set udg_x = x
endif
exitwhen b
set x = x + block
endloop
set x = udg_x
loop
set b = (not IsPointInRegion(udg_Region[n],x,y+block))
if b then
set udg_y = y
endif
exitwhen b
set y = y + block
endloop
call BJDebugMsg("завершение func RightTopVertex, координаты: x1: " + R2S(udg_x) + " y1: " + R2S(udg_y) )
set udg_xx[0] = udg_x
set udg_yy[0] = udg_y
set udg_move = 1
//set udg_previous_movement = 4
endfunction
function TopVertex takes nothing returns nothing
local real block = 32
local real x = udg_x
local real y = udg_y
local integer n = udg_temp_integer
local boolean b1
local boolean b2
//запоминаем, где занята или где свободна. Либо точка справа (x+block,y) или точка слева (x-block,y)
local boolean e1=(IsPointInRegion(udg_Region[n],x-block,y))
local boolean e2=(IsPointInRegion(udg_Region[n],x+block,y))
call BJDebugMsg("запуск func TopVertex" )
loop
//проверяем на отклонение точку слева (x-block,y) и точку справа (x+block,y)
set b2=not((IsPointInRegion(udg_Region[n],x-block,y)==e1) or (IsPointInRegion(udg_Region[n],x+block,y)==e2))
//проверяем сверху точку (x,y+block)
set b1 = (not IsPointInRegion(udg_Region[n],x,y+block))
if (b1 or b2) or (b1 and b2) then
set udg_y = y
endif
exitwhen (b1 or b2) or (b1 and b2)
set y = y + block
endloop
//проверка точки слева (x-block,y)
if IsPointInRegion(udg_Region[n],x-block,y) then
set udg_move = 2 //движение влево свободно
set udg_bbbb[0] = true
//проверка точки справа (x+block,y)
elseif (IsPointInRegion(udg_Region[n],x+block,y)) then
set udg_move = 4 //движение вправо свободно
set udg_bbbb[0] = true
endif
call BJDebugMsg("завершение func TopVertex, move: " + I2S(udg_move) + "коор x"+ R2S(udg_x) + "y" + R2S(udg_y) )
endfunction
function BottomVertex takes nothing returns nothing
local real block = 32
local real x = udg_x
local real y = udg_y
local integer n = udg_temp_integer
local boolean b1
local boolean b2
//запоминаем, где занята или где свободна. Либо точка справа (x+block,y) или точка слева (x-block,y)
local boolean e1=(IsPointInRegion(udg_Region[n],x-block,y))
local boolean e2=(IsPointInRegion(udg_Region[n],x+block,y))
call BJDebugMsg("запуск func BottomVertex" )
loop
//проверяем на отклонение точку слева (x-block,y) и точку справа (x+block,y)
set b2=not((IsPointInRegion(udg_Region[n],x-block,y))==e1 or (IsPointInRegion(udg_Region[n],x+block,y))==e2)
//проверяем снизу точку (x,y-block)
set b1 = (not IsPointInRegion(udg_Region[n],x,y-block))
if (b1 or b2) or (b1 and b2) then
set udg_y = y
endif
exitwhen (b1 or b2) or (b1 and b2)
set y = y - block
endloop
//проверка точки слева (x-block,y)
if IsPointInRegion(udg_Region[n],x-block,y) then
set udg_move = 2 //движение влево свободно
set udg_bbbb[0] = true
//проверка точки справа (x+block,y)
elseif IsPointInRegion(udg_Region[n],x+block,y) then
set udg_move = 4 //движение вправо свободно
set udg_bbbb[0] = true
endif
call BJDebugMsg("завершение func BottomVertex, move: " + I2S(udg_move) + "коор x"+ R2S(udg_x) + "y" + R2S(udg_y) )
endfunction
function LeftVertex takes nothing returns nothing
local real block = 32
local real x = udg_x
local real y = udg_y
local integer n = udg_temp_integer
local boolean b1
local boolean b2
//запоминаем, где занята или где свободна. Либо точка снизу (x,y-block) или точка сверху (x,y+block)
local boolean e1=(IsPointInRegion(udg_Region[n],x,y-block))
local boolean e2=(IsPointInRegion(udg_Region[n],x,y+block))
call BJDebugMsg("запуск func LeftVertex" )
loop
//проверяем точку сверху (x,y+block) и точку снизу (x,y-block)
set b2=not((IsPointInRegion(udg_Region[n],x,y+block)==e2) or (IsPointInRegion(udg_Region[n],x,y-block)==e1))
//проверяем слева точку (x-block,y)
set b1 = (not IsPointInRegion(udg_Region[n],x-block,y))
if (b1 or b2) or (b1 and b2) then
set udg_x = x
endif
exitwhen (b1 or b2) or (b1 and b2)
set x = x - block
endloop
//проверка точки снизу (x,y-block)
if IsPointInRegion(udg_Region[n],x,y-block) then
set udg_move = 1 //движение вниз свободно
set udg_bbbb[0] = true
//проверка точки сверху (x,y+block)
elseif (IsPointInRegion(udg_Region[n],x,y+block)) then
set udg_move = 3 //движение вверх свободно
set udg_bbbb[0] = true
endif
call BJDebugMsg("завершение func LeftVertex, move: " + I2S(udg_move) + "коор x"+ R2S(udg_x) + "y" + R2S(udg_y) )
endfunction
function RightVertex takes nothing returns nothing
local real block = 32
local real x = udg_x
local real y = udg_y
local integer n = udg_temp_integer
local boolean b1
local boolean b2
//запоминаем, где занята или где свободна. Либо точка снизу (x,y-block) или точка сверху (x,y+block)
local boolean e1=(IsPointInRegion(udg_Region[n],x,y-block))
local boolean e2=(IsPointInRegion(udg_Region[n],x,y+block))
call BJDebugMsg("запуск func RightVertex" )
loop
//проверяем точку сверху (x,y+block) и точку снизу (x,y-block)
set b2=not((IsPointInRegion(udg_Region[n],x,y+block)!=e2) or (IsPointInRegion(udg_Region[n],x,y-block)!=e1))
//проверяем справа точку (x-block,y)
set b1 = (not IsPointInRegion(udg_Region[n],x+block,y))
if (b1 or b2) or (b1 and b2) then
set udg_x = x
endif
exitwhen (b1 or b2) or (b1 and b2)
set x = x + block
endloop
//проверка точки сверху (x,y+block)
if IsPointInRegion(udg_Region[n],x,y+block) then
set udg_move = 3 //движение вверх свободно
set udg_bbbb[0] = true
//проверка точки снизу (x,y-block)
elseif (IsPointInRegion(udg_Region[n],x,y-block)) then
set udg_move = 1 //движение вниз свободно
set udg_bbbb[0] = true
endif
call BJDebugMsg("завершение func RightVertex, move: " + I2S(udg_move) + "коор x"+ R2S(udg_x) + "y" + R2S(udg_y) )
endfunction
function Trig_triigger_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local real k = GetUnitDefaultPropWindow(u)
local integer i = R2I(k/32)
local integer c = 0
local integer n = (GetPlayerId(GetTriggerPlayer()))
local real minx
local real miny
local real maxx
local real maxy
local boolean b = false
//local integer id = GetUnitTypeId(u)
call MoveRectTo(udg_Rect_32x32[i],x,y)
call RegionAddRect(udg_Region[n], udg_Rect_32x32[i])
set i = 0
loop
exitwhen i > udg_CountLighting
call DestroyLightning(udg_lightning[i])
set i = i + 1
endloop
set udg_CountVertex = 0
set udg_CountLighting = 0
set udg_temp_integer = n
call RightTopVertex(n,GetUnitX(u), GetUnitY(u))
set udg_CountVertex = 1
loop
exitwhen (udg_xx[0] == udg_x) and (udg_yy[0] == udg_y) and (udg_CountVertex > 1)
if udg_move == 1 then //идем вниз
call ExecuteFunc("BottomVertex")
elseif udg_move == 2 then //идем влево
call ExecuteFunc("LeftVertex")
elseif udg_move == 3 then //идем вверх
call ExecuteFunc("TopVertex")
elseif udg_move == 4 then //идем вправо
call ExecuteFunc("RightVertex")
endif
set udg_xx[udg_CountVertex] = udg_x
set udg_yy[udg_CountVertex] = udg_y
set udg_lightning[udg_CountLighting] = AddLightning("CLPB",true,udg_xx[udg_CountVertex-1],udg_yy[udg_CountVertex-1],udg_xx[udg_CountVertex],udg_yy[udg_CountVertex])
set udg_CountLighting = udg_CountLighting + 1
call BJDebugMsg("кол-во точек: " + I2S(udg_CountVertex))
set udg_CountVertex = udg_CountVertex + 1
endloop
call BJDebugMsg("завершение цикла" )
call BJDebugMsg("координаты: x1: " + R2S(udg_xx[0]) + " y1: " + R2S(udg_yy[0]) + " x2: " + R2S(udg_yy[1]) + " y2: " + R2S(udg_yy[1]) )
set u = null
endfunction
//===========================================================================
function InitTrig_triigger takes nothing returns nothing
set gg_trg_triigger = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_triigger, Player(0), EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
call TriggerAddAction( gg_trg_triigger, function Trig_triigger_Actions )
endfunction
алгоритм такой:
- находим первую крайнюю точку - решил двигать от центра и тикать вправо (границу справа ищу), затем вверх (границу сверзу). Короче выбираю первую попавшуюся точку
- затем двигаем по часовой - то есть вниз. Попутно проверяя отклонения. Естественно, в начале вниз идем, тк двигаемся от верхнего правого угла. А дальше как пойдет (вверх, вниз и так далее), все зависит от сложности геометрической фигуры.
- так будет находить точки, совершая круг. Действие должно вернуться в первую точку, и завершиться.
По факту:
- Простые прямоугольные формы работают , но со сложными фигурами не работают. Бывает не дорисовывает.
- Иногда тупит, может какая сторона не отображается. (один раз норм работал, пришлось изменить код слегка и что-то перестало работать). Это конечно работало с простыми формами, теперь ... На картинке у меня вниз шел, влево, и потом наверх. И что-то ... Как видите
Видоизменял код раз 10. Даже не знаю как сделать. Один так работает, во втором что-то не работает. И так далее. Мб есть похожий алгоритм?
Принятый ответ
Ну вообще, такое делается с помощью алгоритма Грэхема по построению выпуклой оболочки.
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован MpW
И тут у варкрафта что ли проблема - не может создать много молнии (не все молнии может успеть создать = не знаю почему, дебаг норм показывает. все координаты точек показываем норм), лимит операции (вряд ли)?