Трёхмерное движение

Не могу разобраться с одним вопросом. В Варкрафте можно двигать юнита по осям x, y и z. Я хочу сделать вращение. Предположим, что у меня есть дамми юнит, которого я вращаю по осям y и z ( как будто колесо ) то бишь с углом в 90°, но я хочу крутить его, условно, под углом в 45°, то есть двигая и по оси x. Как правило это должно быть реализовано?

Ответ

ArhiMEN, ну тогда хз, с этой штукой мне половина хгм канала пытались помочь, но формулу мне по итогу скинул N1ghtSiren
function PolarProjectionXYZ(x, y, z, dist, GroundAngle, FacingAngle)
    --FacingAngle - 0-360 -- yaw
    --GroundAngle - 0-180 -- pitch
    local x1 = x + dist*SinBJ(GroundAngle)*CosBJ(FacingAngle)
    local y1 = y + dist*SinBJ(GroundAngle)*SinBJ(FacingAngle)
    local z1 = z + dist*CosBJ(GroundAngle)
    --
    return x1,y1,z1
end
надеюсь не составит труда на джасс перенести

ну и сама карта, смотреть там правда нечего, я был абсолютным дауном и клепал недоспеллы на то время (собственно ничего и не изменилось), но мб этот вонючий огрызок как-то сможет помочь
» код
library spelllib initializer SpiritMissile
    globals
        hashtable H = InitHashtable( )
    endglobals
    
    private struct SpiritMissileInfo
        unit u
        unit u1
        unit u2
        real x
        real y
        real speed
        real offsetz
        real a
        real a1
        real dmg
        real radius
        real dist
        real az
        real azs
        integer AttackType
        integer DamageType
        boolean tf
        boolexpr b
    endstruct
    
    private function SpiritMissileMove takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local SpiritMissileInfo A = LoadInteger(H,GetHandleId(t),0)
        local real d = 0
        set A.x = (A.x+A.speed*Cos(A.a)) + A.offsetz*Sin(A.az)*Cos(A.a-A.a1)
        set A.y = (A.y+A.speed*Sin(A.a)) + A.offsetz*Sin(A.az)*Sin(A.a-A.a1)
        
        set A.dist = A.dist-A.speed
        
        call SetUnitX( A.u1, A.x )
        call SetUnitY( A.u1, A.y )
        call SetUnitFlyHeight(A.u1,GetUnitFlyHeight(A.u1) + A.offsetz*Cos(A.az),0)
        /*set bj_lastCreatedUnit = A.u
        call GroupEnumUnitsInRange(TempG,A.x,A.y,A.radius,A.b)
        if A.tf then
            call SetItemPositionEx(TempIt,A.x,A.y)
            set d = DBC(GetItemX(TempIt),GetItemY(TempIt),A.x,A.y)
        endif*/
        if A.dist <= 0 or d > 10 then
            
            //call KillUnit(A.u1)
            call FlushChildHashtable(H,GetHandleId(t))
            call PauseTimer(t)
            call DestroyTimer(t)
            call A.destroy()
            set A.u = null
            set A.u1 = null
            set A.u2 = null
            set A.a = 0.
            set A.a1 = 0.
            set A.speed = 0.
            set A.offsetz = 0.
            set A.dmg = 0.
            set A.dist = 0.
            set A.radius = 0.
            set A.az = 0.
            set A.azs = 0.
            set A.b = null
            set A.AttackType = 0
            set A.DamageType = 0
        else
            set A.az = A.az+(A.azs*bj_DEGTORAD)
            if A.u2 != null then
                set A.a = Atan2(GetUnitY(A.u2)-A.y,GetUnitX(A.u2)-A.x)
            endif
        endif
        
        set t = null
    endfunction
    
    function SpiritMissile takes nothing returns nothing
        local timer t = CreateTimer()
        local SpiritMissileInfo A = SpiritMissileInfo.create()
        
        set A.u = gg_unit_hfoo_0000
        set A.a = 0.00
        set A.a1 = 45.00 * bj_DEGTORAD
        set A.u1 = gg_unit_hfoo_0000
        set A.x = GetUnitX(A.u1)
        set A.y = GetUnitY(A.u1)
        set A.speed = 3
        set A.offsetz = 20
        set A.dmg = 0
        set A.dist = 999
        set A.radius = 100
        set A.az = 0.
        set A.azs = 6
        set A.b = null
        set A.AttackType = 0
        set A.DamageType = 0
        
        if false then
            set A.u2 = GetTriggerUnit()
        endif
        set A.tf = false
        
        call UnitAddAbility(A.u1,'Arav')
        call SetUnitFlyHeight(A.u1,50,0)
        call SetUnitPathing(A.u1,false)
        call SaveInteger(H,GetHandleId(t),0,A)
        call TimerStart(t,0.01,true,function SpiritMissileMove)
        
        set t = null
    endfunction
endlibrary


Views: 88

rsfghd #1 - 1 month ago (изм. ) 2
Голосов: 2
чёт не понятно, что конкретно ты хочешь, вращение юнита по yaw pitch roll или вращение вокруг его оси?
Прикрепленные файлы
ArhiMEN #2 - 1 month ago 0
Голосов: 0
rsfghd, Да вращение такое, но под углом, как бы наискось
rsfghd #3 - 1 month ago 1
Голосов: 1
Прикрепленные файлы
ArhiMEN #4 - 1 month ago 0
Голосов: 0
rsfghd, да, скорее всего, не совсем по этому ролику понятно
rsfghd #5 - 1 month ago 1
Голосов: 1

ArhiMEN, ну тогда хз, с этой штукой мне половина хгм канала пытались помочь, но формулу мне по итогу скинул N1ghtSiren
function PolarProjectionXYZ(x, y, z, dist, GroundAngle, FacingAngle)
    --FacingAngle - 0-360 -- yaw
    --GroundAngle - 0-180 -- pitch
    local x1 = x + dist*SinBJ(GroundAngle)*CosBJ(FacingAngle)
    local y1 = y + dist*SinBJ(GroundAngle)*SinBJ(FacingAngle)
    local z1 = z + dist*CosBJ(GroundAngle)
    --
    return x1,y1,z1
end
надеюсь не составит труда на джасс перенести

ну и сама карта, смотреть там правда нечего, я был абсолютным дауном и клепал недоспеллы на то время (собственно ничего и не изменилось), но мб этот вонючий огрызок как-то сможет помочь
» код
library spelllib initializer SpiritMissile
    globals
        hashtable H = InitHashtable( )
    endglobals
    
    private struct SpiritMissileInfo
        unit u
        unit u1
        unit u2
        real x
        real y
        real speed
        real offsetz
        real a
        real a1
        real dmg
        real radius
        real dist
        real az
        real azs
        integer AttackType
        integer DamageType
        boolean tf
        boolexpr b
    endstruct
    
    private function SpiritMissileMove takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local SpiritMissileInfo A = LoadInteger(H,GetHandleId(t),0)
        local real d = 0
        set A.x = (A.x+A.speed*Cos(A.a)) + A.offsetz*Sin(A.az)*Cos(A.a-A.a1)
        set A.y = (A.y+A.speed*Sin(A.a)) + A.offsetz*Sin(A.az)*Sin(A.a-A.a1)
        
        set A.dist = A.dist-A.speed
        
        call SetUnitX( A.u1, A.x )
        call SetUnitY( A.u1, A.y )
        call SetUnitFlyHeight(A.u1,GetUnitFlyHeight(A.u1) + A.offsetz*Cos(A.az),0)
        /*set bj_lastCreatedUnit = A.u
        call GroupEnumUnitsInRange(TempG,A.x,A.y,A.radius,A.b)
        if A.tf then
            call SetItemPositionEx(TempIt,A.x,A.y)
            set d = DBC(GetItemX(TempIt),GetItemY(TempIt),A.x,A.y)
        endif*/
        if A.dist <= 0 or d > 10 then
            
            //call KillUnit(A.u1)
            call FlushChildHashtable(H,GetHandleId(t))
            call PauseTimer(t)
            call DestroyTimer(t)
            call A.destroy()
            set A.u = null
            set A.u1 = null
            set A.u2 = null
            set A.a = 0.
            set A.a1 = 0.
            set A.speed = 0.
            set A.offsetz = 0.
            set A.dmg = 0.
            set A.dist = 0.
            set A.radius = 0.
            set A.az = 0.
            set A.azs = 0.
            set A.b = null
            set A.AttackType = 0
            set A.DamageType = 0
        else
            set A.az = A.az+(A.azs*bj_DEGTORAD)
            if A.u2 != null then
                set A.a = Atan2(GetUnitY(A.u2)-A.y,GetUnitX(A.u2)-A.x)
            endif
        endif
        
        set t = null
    endfunction
    
    function SpiritMissile takes nothing returns nothing
        local timer t = CreateTimer()
        local SpiritMissileInfo A = SpiritMissileInfo.create()
        
        set A.u = gg_unit_hfoo_0000
        set A.a = 0.00
        set A.a1 = 45.00 * bj_DEGTORAD
        set A.u1 = gg_unit_hfoo_0000
        set A.x = GetUnitX(A.u1)
        set A.y = GetUnitY(A.u1)
        set A.speed = 3
        set A.offsetz = 20
        set A.dmg = 0
        set A.dist = 999
        set A.radius = 100
        set A.az = 0.
        set A.azs = 6
        set A.b = null
        set A.AttackType = 0
        set A.DamageType = 0
        
        if false then
            set A.u2 = GetTriggerUnit()
        endif
        set A.tf = false
        
        call UnitAddAbility(A.u1,'Arav')
        call SetUnitFlyHeight(A.u1,50,0)
        call SetUnitPathing(A.u1,false)
        call SaveInteger(H,GetHandleId(t),0,A)
        call TimerStart(t,0.01,true,function SpiritMissileMove)
        
        set t = null
    endfunction
endlibrary

Прикрепленные файлы
ArhiMEN #6 - 1 month ago 0
Голосов: 0
ну и сама карта, смотреть там правда нечего, я был абсолютным дауном и клепал недоспеллы на то время (собственно ничего и не изменилось), но мб этот вонючий огрызок как-то сможет помочь
Мне нравится твоя самооценка)

Спасибо, постараюсь разобраться
ScorpioT1000 #7 - 1 month ago 0
Голосов: 0
xDestr поковыряй

Там есть нужный дамми и нужные функции