Хочу сделать показ территории деревни молниями. это соединение геометрических фигур. Возникла проблема. Что это мой алгоритм криво работает
существует ли нормальный алгоритм поиска? могу конечно дать код, но без карты бесполезен.
код
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
алгоритм такой:
  1. находим первую крайнюю точку - решил двигать от центра и тикать вправо (границу справа ищу), затем вверх (границу сверзу). Короче выбираю первую попавшуюся точку
  2. затем двигаем по часовой - то есть вниз. Попутно проверяя отклонения. Естественно, в начале вниз идем, тк двигаемся от верхнего правого угла. А дальше как пойдет (вверх, вниз и так далее), все зависит от сложности геометрической фигуры.
  3. так будет находить точки, совершая круг. Действие должно вернуться в первую точку, и завершиться.
По факту:
  1. Простые прямоугольные формы работают , но со сложными фигурами не работают. Бывает не дорисовывает.
  1. Иногда тупит, может какая сторона не отображается. (один раз норм работал, пришлось изменить код слегка и что-то перестало работать). Это конечно работало с простыми формами, теперь ... На картинке у меня вниз шел, влево, и потом наверх. И что-то ... Как видите
Видоизменял код раз 10. Даже не знаю как сделать. Один так работает, во втором что-то не работает. И так далее. Мб есть похожий алгоритм?

Принятый ответ

Ну вообще, такое делается с помощью алгоритма Грэхема по построению выпуклой оболочки.
`
ОЖИДАНИЕ РЕКЛАМЫ...
1
27
5 лет назад
Отредактирован MpW
1
ладно ошибки исправил. Но обнаруживаются другие проблемы - отображаем только наружные границы. А во внутренние не учитываем.
И тут у варкрафта что ли проблема - не может создать много молнии (не все молнии может успеть создать = не знаю почему, дебаг норм показывает. все координаты точек показываем норм), лимит операции (вряд ли)?
вот слева почему-то не создалась молния =(
Загруженные файлы
2
18
5 лет назад
2
Ну вообще, такое делается с помощью алгоритма Грэхема по построению выпуклой оболочки.
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.