• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Advanced homing projectile

Status
Not open for further replies.
Level 13
Joined
Mar 29, 2012
Messages
530
How to make a projectile to properly home-in to a target unit?
My problem is about the mathematical calculation.

Currently, I've managed to make the projectile move to a 3D point towards its facing direction with offset by [speed base] plus offset by [turn acceleration] towards the target unit --> on every frame update (32 iteration per second). But sometimes, if the projectile missed the target unit, it will just spin around the target because maybe the [turn acceleration] is too low to turn the projectile towards target.
If I set [turn acceleration] to a higher value, the projectile would not have a good curve.
How do I achieve this?

JASS:
set vectorX = .targetX - .posX
set vectorY = .targetY - .posY
set vectorZ = .targetZ - .posZ

set dist = GetDistance2D(vectorX, vectorY)
set angleZ = AngleZ(vectorX, vectorY)
set anglePointsZ = AnglePointsZ(dist, vectorZ)

set .posX = ((.posX + ROCKETS_SPEED_BASE[.node.level] * Cos(.roll) * Cos(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Cos(angleZ) * Cos(anglePointsZ)
set .posY = ((.posY + ROCKETS_SPEED_BASE[.node.level] * Sin(.roll) * Cos(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Sin(angleZ) * Cos(anglePointsZ)
set .posZ = ((.posZ + ROCKETS_SPEED_BASE[.node.level] * Sin(.pitch))) + ROCKETS_TURN_ACCELERATION[.node.level] * Sin(anglePointsZ)

set vectorX = .posX - .lastPosX
set vectorY = .posY - .lastPosY
set vectorZ = .posZ - .lastPosZ

call SetEffectOrientation3D(vectorX, vectorY, vectorZ)
set .pitch = AnglePointsZ(GetDistance2D(vectorX, vectorY), vectorZ)
JASS:
function GetDistance2D takes real x, real y returns real
    return SquareRoot(x * x + y * y)
endfunction

function GetDistance3D takes real x, real y, real z returns real
    return SquareRoot(x * x + y * y + z * z)
endfunction

function AngleZ takes real x, real y returns real
    return Atan2(y, x)
endfunction

function AnglePointsZ takes real distance2D, real z returns real
    return Atan2(z, distance2D)
endfunction

function GetTerrainZ takes real x, real y returns real
    call MoveLocation(zLoc, x, y)
    return GetLocationZ(zLoc)
endfunction

function GetUnitTerrainZ takes unit targetUnit, real x, real y returns real
    local real height
    
    set height = GetUnitFlyHeight(targetUnit) + TARGET_CHEST_HEIGHT
    
    return height + GetTerrainZ(x, y)
endfunction

function GetDistanceToUnit3D takes real x, real y, real z, unit targetUnit returns real
    local real targetX = GetUnitX(targetUnit)
    local real targetY = GetUnitY(targetUnit)
    local real targetZ = GetUnitTerrainZ(targetUnit, targetX, targetY)
    
    return GetDistance3D(targetX-x, targetY-y, targetZ-z)
endfunction

function SetEffectOrientation3D takes real x, real y, real z returns nothing
    // by Wareditor
    local real ax
    local real ay
    local real px
    local real py
   
    if x == 0 and y == 0 then
        if z > 0 then
            set ax = -bj_PI*0.5
        else 
            set ax = bj_PI*0.5
        endif
    elseif z != 0 then
        set ax = RAbsBJ(x)
        set ay = RAbsBJ(y)
        set px = ax / (ax + ay)
        set py = 1 - px
        if y == 0 then
            set ax = 0
        else
            set ax = Atan(z/y)*py
        endif
        if x == 0 then
            set ay = 0
        else 
            set ay = -Atan(z/x)*px
        endif
    endif
    set .pitch = ay
    set .roll = Atan2(y, x)
   
    call BlzSetSpecialEffectOrientation(.rocket, ax, .lastPitch, .roll)
    call BlzSetSpecialEffectPitch(.rocket, .pitch)
    set .lastPitch = .pitch
endfunction

My current idea:
I might make the [turn acceleration] to have dynamic value, for example, the farther the projectile is from the target unit, [turn acceleration] will accordingly increase. But I have no idea how to achieve this, mathematically.
 
Status
Not open for further replies.
Top