• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Create a faction for Warcraft 3 and enter Hive's 19th Techtree Contest: Co-Op Commanders! Click here to enter!
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 21st Texturing Contest: Upgrade is now concluded, time to vote for your favourite set of icons! Click here to vote!

Advanced homing projectile

Status
Not open for further replies.
Level 13
Joined
Mar 29, 2012
Messages
542
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