• 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.

Shameful help with angle between two points

Status
Not open for further replies.
Level 14
Joined
Aug 30, 2004
Messages
909
Being a fairly educated man I'm quite ashamed to ask for help on this point...

Following Bribe's advice, I am changing my custom movement system from using a giant array of points to just using 2 locations that I move with the MoveLocation JASS command. I hit a bit of a snag and am hoping someone can help me translate the following code so that it doesn't use any points.

The following section of a trigger is meant to get the location of a moving unit (u), and move it by tempSpeed in the direction that it's facing. Because the trigger fires every .02 seconds, it's important that it be written efficiently, which is the point of all the changes. Here's what I have so far:

  • Custom script: set udg_x = GetUnitX(udg_u)
  • Custom script: set udg_y = GetUnitY(udg_u)
  • Custom script: call MoveLocation(udg_LocationMove1, udg_x, udg_y)
  • Set tempPointOffset = (LocationMove1 offset by tempSpeed towards (Facing of u) degrees)
  • Custom script: call SetUnitX (udg_u, GetLocationX (udg_tempPointOffset))
  • Custom script: call SetUnitY (udg_u, GetLocationY (udg_tempPointOffset))
  • Custom script: call RemoveLocation (udg_tempPointOffset)
The first three lines get the starting location of the ship and move a point variable LocationMove1 to that point. That's good I think.

The last four lines are what needs help. As it's written, tempPointOffset is the point variable that stores where unit "u" will be moved to.

I would like to change the code so that I just move LocationMove1 by tempSpeed in the direction that "u" is facing, but I don't know the geometry to do that (hence the shame). Then I could use the SetUnitX commands to move "u" to LocationMove1.

Thank you very much for your help.

Darwin
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
GUI and efficient coding are muturilly exclusive sadly... Even using a global rather than a local for some tasks slows execution down.

This is due to globals being at a fixed point in memory while locals are on the stack. As the stack for a thread is mostly in the cache it will execute faster than a variable that will likly be unloaded into memory after use. Globals may also exibit volitile behaviour so force memory writes (which is 10-20 times slower than a stack write if the stack is in cache). Actual speed gain is a lot lower in reality as the variable lookup system in JASS is far from efficient.
 
Level 14
Joined
Aug 30, 2004
Messages
909
GUI and efficient coding are muturilly exclusive sadly... Even using a global rather than a local for some tasks slows execution down.

This is due to globals being at a fixed point in memory while locals are on the stack. As the stack for a thread is mostly in the cache it will execute faster than a variable that will likly be unloaded into memory after use. Globals may also exibit volitile behaviour so force memory writes (which is 10-20 times slower than a stack write if the stack is in cache). Actual speed gain is a lot lower in reality as the variable lookup system in JASS is far from efficient.

This makes me sad, but I simply don't have time to learn JASS. I also want to move out of the WC3 editor and into SC2 after this map. I think my needs are pretty modest though; I have no lag at all on my computer; I just want to make it as efficient as I can.

It is true that using SetUnitX type commands are more efficient than working with array's of points though, correct?
 
in JASS, we usually or always use coordinates...as D4RK_G4ND4LF pointed out, it's "much faster and additionally they don't interrupt orders"...

This is like PolarProjectionBJ which causes your unit to move forward...
JASS:
call SetUnitX(u, x + offset * Cos(angle * bj_DEGTORAD))
call SetUnitY(u, y + offset * Sin(angle * bj_DEGTORAD))
 
Level 15
Joined
Oct 16, 2010
Messages
942
This is a small trig lib I wrote which may help you. If not, then good luck.

JASS:
library TrigFunctions

    function GetProjectedX takes real currentX, real hypotenuse, real angle returns real
        return (currentX + (hypotenuse * Cos(angle * bj_DEGTORAD)))
    endfunction
    
    function GetProjectedY takes real currentY, real hypotenuse, real angle returns real
        return (currentY + (hypotenuse * Sin(angle * bj_DEGTORAD)))
    endfunction
    
    function DistanceBetweenPositions takes real X1, real Y1, real X2, real Y2 returns real
        local real X = X2 - X1
        local real Y = Y2 - Y1
        return SquareRoot((X * X) + (Y * Y))
    endfunction
    
    function GetAngle takes real X1, real Y1, real X2, real Y2 returns real
        local real angle = (Atan2((Y2 - Y1), (X2 - X1)) * bj_RADTODEG)
        if (angle > 360) then
            loop
                set angle = angle - 360
                exitwhen (angle <= 360)
            endloop
        elseif (angle < 0) then
            loop
                set angle = angle + 360
                exitwhen (angle >= 0)
            endloop
        endif
        return angle
    endfunction
    
    function AngleOffset takes real Angle1, real Angle2, real Amount returns real
        local real difference
            
        set difference = Angle1 - Angle2
        if (difference < 0) then 
            set difference = difference * -1
        endif
        if (difference <= Amount) then
            return Angle2
        else
            if (difference > 180) then 
                set Amount = Amount * -1
            endif
            if (Angle1 > Angle2) then
                set Angle1 = Angle1 - Amount
            else
                set Angle1 = Angle1 + Amount
            endif
        endif
            
        if (Angle1 > 360) then
            loop
                set Angle1 = Angle1 - 360
                exitwhen (Angle1 <= 360)
            endloop
        elseif (Angle1 < 0) then
            loop
                set Angle1 = Angle1 + 360
                exitwhen (Angle1 >= 0)
            endloop
        endif
        
        return Angle1
    endfunction
    
endlibrary

So the code you would want would look something like this:

JASS:
call SetUnitX(udg_u, GetProjectedX(GetUnitX(udg_u), udg_tempSpeed, GetUnitFacing(udg_u)))
 call SetUnitY(udg_u, GetProjectedY(GetUnitY(udg_u), udg_tempSpeed, GetUnitFacing(udg_u)))
 
Level 14
Joined
Aug 30, 2004
Messages
909
Thanks to everyone for helping so far (+rep to all of you). So far that has all worked out fine. I do have one more question though:

I'm using 2 points to determine angles for my AI system. Basically, I need to know the angle between a unit "Fliers[a2]" and his target "AiTarget[a2]", where a2 is an integer and both Fliers and AiTarget are unit arrays.

I've used the MoveLocation function to move points onto their locations and then set Math2 = (angle from location1 to location2) to get the angle between the two units. I suspect there's a way of using arcsines or arctangents or some such math to get that angle from the x,y coordinates of the two points. I can get the coordinates with the GetUnitX actions, and then subtract them to get the x-distance between the units and the y-distance between the units, but how do I turn those into an angle?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
in JASS, we usually or always use coordinates...as D4RK_G4ND4LF pointed out, it's "much faster and additionally they don't interrupt orders"...

This is like PolarProjectionBJ which causes your unit to move forward...
JASS:
call SetUnitX(u, x + offset * Cos(angle * bj_DEGTORAD))
call SetUnitY(u, y + offset * Sin(angle * bj_DEGTORAD))

And in JASS people are more likely to use radians so there will be no DEGTORAD conversions unless a facing of a unit is used.
 
hooray! people are referring to me :grin:

Storing in radians improved trigonometry efficiency (saves a float multiplication) but decreases facing angle efficiency (adds a float multiplication).

I read that unit facing is not that accurate anyway
was something between 5 and 15 degrees it was off to the real angle if I remember right

You can use the "GetAngle()" function from my posted lib above.

So:

JASS:
local real x = GetAngle(GetUnitX(Fliers[a2]), GetUnitY(Fliers[a2]), GetUnitX(AiTarget[a2], GetUnitY(AiTarget[a2]))

or just use Atan or Atan2 directly
(or the law of cosines http://en.wikipedia.org/wiki/Law_of_cosines)

(and you probably wanted to write angle instead of x but since it's just a name it's not wrong yet :p)
 
Status
Not open for further replies.
Top