Добавлен Берги,
опубликован
Рисуем стрелочки и прочие маркеры попиксельно.
Вот этим вот пикселем
Почему попиксельно? да потому что не завезли функцию для поворота изображения, ну а что нам мешает делать свои?
В статье про квадратные изображения, мы рисовали маркеры целиком, теперь же я покажу как это делает отдельными блоками.
Почему попиксельно? да потому что не завезли функцию для поворота изображения, ну а что нам мешает делать свои?
В статье про квадратные изображения, мы рисовали маркеры целиком, теперь же я покажу как это делает отдельными блоками.
Функция для отрисовки конуса
function CreateVisualConusForUnitBySplat(hero,flag,long,step,range,angleSector)
local image={}
local image2={}
local pid=GetPlayerId(GetOwningPlayer(hero))
local data=HERO[pid]
local size=step/3
local r60=70//size
local r40=50//size
local LastMouseX=0
for i=1,long*2 do
image[i]=CreateImage(ImportPath.."\\pointerORIG",16,16,16,4000,4000,0,0,0,150,4)
SetImageColor(image[i],0,255,0,128)
SetImageRenderAlways(image[i], true)
if GetLocalPlayer()~=Player(pid) then
ShowImage(image[i],false)
else
ShowImage(image[i],true)
end
end
local distance=0
local mouseMoving=false
local savedDistance=0
local lastAngle=0
local delta=0
local angle=0
local function Destroy()
DestroyTimer(GetExpiredTimer())
--data.MarkIsActivated=true
--print("destroy")
for i=1,#image do
DestroyImage(image[i])
DestroyImage(image2[i])
end
end
local curAngle=GetUnitFacing(hero)
local iter=0
local curBlock=0
TimerStart(CreateTimer(), TIMER_PERIOD, true, function()
local xs,ys=MoveXY(GetUnitX(hero)-16,GetUnitY(hero)-16,0,curAngle)--стартовое смещение и это центр юнита
iter=iter+1
angle=AngleBetweenXY(xs, ys, GetPlayerMouseX[pid], GetPlayerMouseY[pid])/bj_DEGTORAD--data.AngleMouse
curAngle=lerpTheta(curAngle,angle,TIMER_PERIOD*8)
if LastMouseX == GetPlayerMouseX[pid] then
mouseMoving=false
else
mouseMoving=true
end
LastMouseX = GetPlayerMouseX[pid]
delta=curAngle-lastAngle
lastAngle=curAngle
if mouseMoving then
distance=DistanceBetweenXY(GetPlayerMouseX[pid],GetPlayerMouseY[pid],GetUnitXY(hero))
savedDistance=DistanceBetweenXY(GetPlayerMouseX[pid],GetPlayerMouseY[pid],GetUnitXY(hero))
else
distance=savedDistance
end
local block=0
for _=1,#image do
distance=distance-step
if distance>=0 then
block=block+1
end
end
local k=0
local k2=0
local a=0
local k3=0
local pointToRange=range
local pointToRange2=range*.87
for i=1,#image do
if i<=angleSector then
--рисуем полукруг
a=a+step
k=k+1
local nx,ny=MoveXY(xs,ys,range,-angleSector/2+curAngle+a)
SetImagePosition(image[i],nx,ny,0)
else
local rxs,rys=MoveXY(xs,ys,range,-angleSector/2+curAngle+k*step)
local angleR=AngleBetweenXY(rxs,rys,xs, ys)/bj_DEGTORAD
k2=k2+1
pointToRange=pointToRange-step
if pointToRange>0 then
local nx,ny=MoveXY(rxs,rys,step*k2,angleR)
SetImagePosition(image[i],nx,ny,0)
else
k3=k3+1
pointToRange2=pointToRange2-step
if pointToRange2>0 then
local nx,ny=MoveXY(rxs,rys,step*k2,angleR)
local nx2,ny2=MoveXY(nx,ny,step*k3,angleR-angleSector*2)
SetImagePosition(image[i],nx2,ny2,0)
end
end
end
end
if flag==1 then
if not data.MarkIsActivated then
Destroy()
end
end
end)
end
Результат
Конус выдран из адмирала и не адаптирован под импорт
Функция для отрисовки динамической стрелки
---@param hero "герой"
---@param flag "Параметры_завершения"
---@param long "Число_блоков"
---@param step "Ширина_блока"
---@param minlong "Милимальное_число_отображаемых_блоков
function CreateVisualPointerForUnitBySplat(hero, flag, long, step, minlong)
local image = {}
local image2 = {}
local pid = GetPlayerId(GetOwningPlayer(hero))
--local data = HERO[pid]
local size = step / 3
local r60 = 70 // size
local r40 = 50 // size
local LastMouseX = 0
long=long//step
minlong=minlong//step
for i = 1, long do
image[i] = CreateImage("pointerORIG", 16, 16, 9999, 4000, 4000, 0, 0, 0, 0, 4)
SetImageColor(image[i], 0, 255, 0, 128)
SetImageRenderAlways(image[i], true)
if GetLocalPlayer() ~= Player(pid) then
ShowImage(image[i], false)
else
ShowImage(image[i], true)
end
image2[i] = CreateImage("pointerORIG", 16, 16, 9999, 4000, 4000, 0, 0, 0, 0, 4)
SetImageColor(image2[i], 0, 255, 0, 128)
SetImageRenderAlways(image2[i], true)
if GetLocalPlayer() ~= Player(pid) then
ShowImage(image2[i], false)
else
ShowImage(image2[i], true)
end
end
local distance = 0
local mouseMoving = false
local savedDistance = 0
local lastAngle = 0
local delta = 0
local angle = 0
local function Destroy()
DestroyTimer(GetExpiredTimer())
for i = 1, #image do
DestroyImage(image[i])
DestroyImage(image2[i])
end
end
local curAngle = 180 + AngleBetweenXY(GetPlayerMouseX[pid], GetPlayerMouseY[pid], GetUnitXY(hero)) / bj_DEGTORAD--GetUnitFacing(hero)
local iter = 0
local curBlock = 0
TimerStart(CreateTimer(), TIMER_PERIOD, true, function()
local rxs, rys = GetUnitXY(hero)
if flag == 2 then
--rxs, rys = data.xStand, data.yStand
end
local xs, ys = MoveXY(rxs - 16, rys - 16, 40, curAngle)--стартовое смещение и это центр юнита
local xs2, ys2 = 0, 0
iter = iter + 1
xs, ys = MoveXY(xs, ys, 40, curAngle + 90)
xs2, ys2 = MoveXY(xs, ys, 80, curAngle - 90)
local errAngle = 2.5
if flag == 2 then
--errAngle = 5
end
angle = errAngle + AngleBetweenXY(xs, ys, GetPlayerMouseX[pid], GetPlayerMouseY[pid]) / bj_DEGTORAD--data.AngleMouse
local distMouse = DistanceBetweenXY(GetPlayerMouseX[pid], GetPlayerMouseY[pid], rxs, rys)
--print(distMouse)
if distMouse >= 90 then
curAngle = lerpTheta(curAngle, angle, TIMER_PERIOD * 8)
end
if LastMouseX == GetPlayerMouseX[pid] then
mouseMoving = false
else
mouseMoving = true
end
LastMouseX = GetPlayerMouseX[pid]
delta = curAngle - lastAngle
lastAngle = curAngle
if mouseMoving then
distance = DistanceBetweenXY(GetPlayerMouseX[pid], GetPlayerMouseY[pid], rxs, rys)
savedDistance = DistanceBetweenXY(GetPlayerMouseX[pid], GetPlayerMouseY[pid], rxs, rys)
else
distance = savedDistance
end
local block = 0
for _ = 1, #image do
distance = distance - step
if distance >= 0 then
block = block + 1
end
end
if block <= 61 then
block = 61
end
curBlock = R2I(lerpTheta(curBlock, block, TIMER_PERIOD * 16))
if minlong ~= nil then
if minlong >= curBlock then
curBlock = minlong
end
end
local k = 0
local k2 = 0
for i = 1, #image do
if i < curBlock then
local nx, ny = 0, 0
if i >= curBlock - r60 and i <= curBlock - r40 then
--print(i.."поворот на 90")
k = k + 1
local axs, ays = MoveXY(xs, ys, (curBlock - r60) * step, curAngle)
nx, ny = MoveXY(axs, ays, step * k, curAngle + 90)
SetImagePosition(image[i], nx, ny, 0)
local axs2, ays2 = MoveXY(xs2, ys2, (curBlock - r60) * step, curAngle)
nx, ny = MoveXY(axs2, ays2, step * k, curAngle - 90)
SetImagePosition(image2[i], nx, ny, 0)
else
if i >= curBlock - r40 then
local axs, ays = MoveXY(xs, ys, (curBlock - r60) * step, curAngle)
local axs2, ays2 = MoveXY(xs2, ys2, (curBlock - r60) * step, curAngle)
local px, py, px2, py2 = 0, 0, 0, 0
px, py = MoveXY(axs, ays, step * k, curAngle + 90)
px2, py2 = MoveXY(axs2, ays2, step * k, curAngle - 90)
k2 = k2 + 1
if curBlock <= r60 then
--print("лишняяотрисовка")
SetImagePosition(image[i], OutPoint, OutPoint, 0)
SetImagePosition(image2[i], OutPoint, OutPoint, 0)
else
nx, ny = MoveXY(px, py, step * (k2), curAngle - 45)
SetImagePosition(image[i], nx, ny, 0)
nx, ny = MoveXY(px2, py2, step * (k2), curAngle + 45)
SetImagePosition(image2[i], nx, ny, 0)
end
else
nx, ny = MoveXY(xs, ys, step * i, curAngle)--вот так всё отлично работает
SetImagePosition(image[i], nx, ny, 0)
nx, ny = MoveXY(xs2, ys2, step * i, curAngle)
SetImagePosition(image2[i], nx, ny, 0)
end
end
else
SetImagePosition(image[i], OutPoint, OutPoint, 0)
SetImagePosition(image2[i], OutPoint, OutPoint, 0)
end
end
if flag == 1 then
if not MarkerIsON[GetHandleId(hero)] then
Destroy()
end
end
end)
end
Результат
Пояснения к коду
Через параметр step, задаётся плотность наполнения пикселями, чем этот параметр меньше, тем ярче и плотнее стрелка. Фигуры можно рисовать любые главное придумать формулу и каждый кадр перерисовывать её относительно угла поворота курсора.
Заполнение 1
Заполнение 1
Заполнение 5
Заполнение 10
Чем меньше пикселей, тем слабее нагрузка, можно использовать для слабых ПК, хотя и так общее падение fps на моем ПК 10 летней давности с 360, до 340, на step=1
В общем вызываем функцию через
В общем вызываем функцию через
CreateVisualPointerForUnitBySplat(hero,1,900,5,900)
где
long (900) - максимальная длина стрелки
step (5) - шаг и качество
minlong (900) - минимальная длина стрелки
Если максимальное и минимальное значения указать разными, то стрелка будет трансформироваться согласно положению курсора, в нашем случае для волны силы это не нужно, ведь её длина всегда максимальна
long (900) - максимальная длина стрелки
step (5) - шаг и качество
minlong (900) - минимальная длина стрелки
Если максимальное и минимальное значения указать разными, то стрелка будет трансформироваться согласно положению курсора, в нашем случае для волны силы это не нужно, ведь её длина всегда максимальна
И карта пример по кнопке получить
Содержание
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Если есть способы как избежать артефактов, то буду рад этой помощи