• 🏆 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!

Math help - Angles, speed of missiles

Status
Not open for further replies.
Level 7
Joined
Nov 19, 2015
Messages
283
I have a missile trigger. The spell can be unit target or point target. When it is a unit target I also check if the unit is moving.

This is complex so for the brainy ones out there.

If the target is moving I set the angle of the missile to a new point. I need this new point to be where the target would walk if it continued at its normal speed. This allows the missile to hit the target even though they have moved.

So I have:
The casters position
The speed of the missile
The targets current position
The targets move speed
The facing angle of the target

So I need to know the angle to fire my missile to hit the moving target.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
Take a look at here:
http://www.gamasutra.com/blogs/Kain...edictive_Aim_Mathematics_for_AI_Targeting.php

The calculations you are doing is under category:
Strategy #3 - Assuming Zero Acceleration:

The thing makes calculations harder is speed of your missile is constant instead of the time it takes for missile to hit target.(For example cluster rockets spell by blizzard, missiles takes constant time to travel no matter what the distance is)
 
Level 23
Joined
Feb 6, 2014
Messages
2,466
You just use The Law of Cosine to calculate the time it takes for the missile to hit when the missile is fired the correct angle.


150804d1449132192-math-help-angles-speed-missiles-how-done.jpg



The resulting equation is (following the figure's naming)

t = (-2*d*u*Cos(A) + sqrt((2*d*u*Cos(A))*(2*d*u*Cos(A)) + 4*(m*m - u*u)*d*d))/(2*(m*m - u*u))

now you might ask, "but I need the firing angle" and "how can I find angle A"
Well, you can use Law of Sines
But first, you need to get angle A. Basically
A = (Facing Angle of Target) + (Angle from Missile Source Loc to Target Loc)
based on observation on the figure. Then since you know time t, you can calculate all sides of the triangle. Simply use Sine Law for the correct firing angle. But I recommend you not finding the firing angle at all. If the missile source is going to be ordered, (e.g. an AI), then just use something like this
  • Set TempPoint = Position of Target
  • //t is the one you calculated
  • Set TempPoint2 = TempPoint offset by (Movement Speed of Target*t) towards Facing Angle of Target
  • Unit - Issue Order to (Cast some Skill shot) at TempPoint2
  • //Remove leaks
 

Attachments

  • how it is done.jpg
    how it is done.jpg
    57.6 KB · Views: 498
Last edited:
Level 7
Joined
Nov 19, 2015
Messages
283
Im going to have to digest this first. Thanks guys for the Law of cosine and FLux, you explain it really well.

I think I can use this for another spell where I throw another missile to deflect incoming missiles.

Edit: can someone write this out in a single line of custom script jass for me please.
I don't know how to get the move speed, facing angle or distance in jass since I only use GUI.

EDIT: Ok so I've implemented it into my map and its great. It almost always hits when the target is running at an angle away from the caster however it always misses when the unit is running at an angle towards the caster. The missile is thrown to far in front of the target and misses. I think this might be due to units not walking in a straight line from point to point.
 
Last edited:
Level 23
Joined
Feb 6, 2014
Messages
2,466
Ok so I've implemented it into my map and its great. It almost always hits when the target is running at an angle away from the caster however it always misses when the unit is running at an angle towards the caster. The missile is thrown to far in front of the target and misses. I think this might be due to units not walking in a straight line from point to point.

Well yeah of course it will not hit the target when it target changes direction, the equation I provided assumed it will continue to move in a straight line at the time it was targeted (as seen in the figure). Unless you develop an API in warcraft 3's pathing algorithm, you're limited to assume the target moves in a straight line.

Also note that, when the caster has a casting time/cast point, it will not guarantee a hit because there is a delay before the missile is launch. The equation I provided assumed no time delay so if there is a time delay, you're gonna have to introduce it in the equation.
 
Level 7
Joined
Nov 19, 2015
Messages
283
Well yeah of course it will not hit the target when it target changes direction, the equation I provided assumed it will continue to move in a straight line at the time it was targeted (as seen in the figure). Unless you develop an API in warcraft 3's pathing algorithm, you're limited to assume the target moves in a straight line.

Also note that, when the caster has a casting time/cast point, it will not guarantee a hit because there is a delay before the missile is launch. The equation I provided assumed no time delay so if there is a time delay, you're gonna have to introduce it in the equation.

I read in a post somewhere that units walk in a curve even when ordered to walk from point A to point B in a straight line. I can't remember where I saw this but it was for a TD map and the person noticed that units walk at a slight curve rather than a straight line.

My spell has no cast time or cast point. I was wondering, how long it takes for a unit to reach its movespeed, since it looks like warcraft has a walk and a run speed. Perhaps it takes time for a unit to reach its maximum movespeed. Just so I can easily input it as a single line of custom script.

Also, could you tell me the code to get:
Unit movespeed, unit facing angle, angle from A-B, Square root, distance from A-B.
 
Last edited:
Level 23
Joined
Feb 6, 2014
Messages
2,466
I don't observe this at all, units will always move in a straightline whenever possible.

And another thing, units move at a constant speed, they're not like vehicles which accelerates.

Codes? Hmm I'm currently on phone but if memory serves me right it is:
GetUnitMoveSpeed(unit)
GetUnitFacing(unit)
Atan2(y2 - y1, x2 - x1)
SquareRoot(real number)
SquareRoot((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)) <-came from Pythagorean theorem
 
Last edited:
Level 21
Joined
Mar 27, 2012
Messages
3,232
Units in WC3 don't have multiple speeds.

What you can get inaccuracies from:
1. Propulsion angle - the unit doesn't make the whole turn before starting movement. This angle is what defines how much the angle can be off.
Useful for fast movement, because you don't typically want units to move in a specific line, but rather in a general direction.
2. Units bumping into each other. They need to figure out what to do about this and the limit on mini-orders seems to be 1 per frame per player(about 30 per second).
3. Turn rate. If the unit needs to turn too much it will not move while turning.
4. Pathfinding quirks. It might not be 100% accurate.
 
Level 7
Joined
Nov 19, 2015
Messages
283
Units in WC3 don't have multiple speeds.

What you can get inaccuracies from:
1. Propulsion angle - the unit doesn't make the whole turn before starting movement. This angle is what defines how much the angle can be off.
Useful for fast movement, because you don't typically want units to move in a specific line, but rather in a general direction.
2. Units bumping into each other. They need to figure out what to do about this and the limit on mini-orders seems to be 1 per frame per player(about 30 per second).
3. Turn rate. If the unit needs to turn too much it will not move while turning.
4. Pathfinding quirks. It might not be 100% accurate.

Wow, I always wondered what the propulsion angle was. This really helps. Is this also for the spell casting or an order given. Perhaps the facing angle of a unit is not angle from cast to target when they first cast it.

I test with no units bumping and also with the unit running is a straight line.
 
Level 7
Joined
Nov 19, 2015
Messages
283
Well, I know that the most foolproof way of making a unit not care about angle when casting is giving it 0 speed. It won't turn then.

Yea, probs wont make help here. I guess its not 100% important that its not always accurate but maybe in other peoples maps it might be. I just have it so that the players has to be more reactive when dodging the missile.
 
Level 23
Joined
Feb 6, 2014
Messages
2,466
What are you trying to achieve exactly?

PS: I applied the same concept in the AI of my map and people say: "The AI is too good at targeting". However I store repeating calculations in a variable for efficiency like (s*s - m*m)
A little thing I dont love is AI. Too great accurary T_T
This is fun to play with, it has AI too although it seems they're pretty good but I love challenges.
 
Level 7
Joined
Nov 19, 2015
Messages
283
What are you trying to achieve exactly?

PS: I applied the same concept in the AI of my map and people say: "The AI is too good at targeting". However I store repeating calculations in a variable for efficiency like (s*s - m*m)

I have a dagger that when thrown will travel in a straight line until it hits something or reaches maximum distance. If targeting the ground it will be aimed in that direction. If aimed at a unit, if the unit is moving, it will shoot to the predicted location.

If possible I would like my targeting to be as accurate as your AI. The missile has only a 30 unit range of detection. Any rounding during the calculation may perhaps offset it enough to miss. It only misses when the target is running perpendicular and towards the caster. In the diagram the red parts are when it will miss, shooting too far forward having the dagger arrive early and missing the target.

Angles.png

Here are my triggers. Perhaps my numbers are not as accurate due to the way it is calculated.
  • Kunai
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Throw Kunai
      • (Target item of ability being cast) Equal to No item
    • Actions
      • Set Player = (Owner of (Triggering unit))
      • Set unit[0] = (Triggering unit)
      • Set TempLoc[0] = (Position of unit[0])
      • Set TempLoc[1] = (Target point of ability being cast)
      • Set unit[1] = (Target unit of ability being cast)
      • Set missile_target = No unit
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • unit[1] Equal to No unit
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering unit) has buff Sharingan ) Equal to True
            • Then - Actions
              • Set temp_group = (Units within 100.00 of TempLoc[1])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in temp_group) Greater than or equal to 1
                • Then - Actions
                  • Set missile_target = (Random unit from temp_group)
                  • Set TempLoc[2] = (Position of missile_target)
                • Else - Actions
                  • Set missile_target = No unit
                  • Set TempLoc[2] = (Target point of ability being cast)
              • Custom script: call DestroyGroup(udg_temp_group)
            • Else - Actions
              • Set TempLoc[2] = (Target point of ability being cast)
        • Else - Actions
          • Set missile_target = unit[1]
          • Set TempLoc[2] = (Position of unit[1])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitMoving[(Custom value of missile_target)] Equal to True
          • missile_target Not equal to No unit
        • Then - Actions
          • -------- Law of Cosine --------
          • -------- Angle A --------
          • Set real[0] = ((Facing of missile_target) + (Angle from TempLoc[0] to TempLoc[2]))
          • -------- Distance --------
          • Set real[1] = ((Distance between TempLoc[0] and TempLoc[2]) - 50.00)
          • -------- Missile speed --------
          • Set real[2] = 1250.00
          • -------- -2*D*Tspeed*cos(A) --------
          • Set real[3] = ((-2.00 x real[1]) x ((Current movement speed of missile_target) x (Cos(real[0]))))
          • -------- 4*D*D*((Mspeed^2)-(Tspeed^2)) --------
          • Set real[4] = ((4.00 x (real[1] x real[1])) x ((real[2] x real[2]) - ((Current movement speed of missile_target) x (Current movement speed of missile_target))))
          • -------- 2*((Mspeed^2)-(Tspeed^2)) --------
          • Set real[5] = (2.00 x ((real[2] x real[2]) - ((Current movement speed of missile_target) x (Current movement speed of missile_target))))
          • -------- Final --------
          • Set real[6] = ((real[3] + (Square root(((real[3] x real[3]) + real[4])))) / real[5])
          • Set real[7] = ((real[3] - (Square root(((real[3] x real[3]) + real[4])))) / real[5])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • real[6] Less than or equal to real[7]
              • real[6] Greater than or equal to 0.00
            • Then - Actions
              • Set real[8] = real[6]
            • Else - Actions
              • Set real[8] = real[7]
          • Set TempLoc[3] = (TempLoc[2] offset by ((Current movement speed of missile_target) x real[8]) towards (Facing of missile_target) degrees)
        • Else - Actions
          • Set TempLoc[3] = TempLoc[2]
      • Set TempLoc[4] = (TempLoc[0] offset by 50.00 towards missile_angle degrees)
      • Set missile_angle = (Angle from TempLoc[4] to TempLoc[3])
      • Set missile_damage = 1.00
      • Set missile_distance = 2500.00
      • Set missile_health = (missile_damage x 1.00)
      • Set missile_homing = 0.00
      • Set missile_knockback = 0.00
      • Set missile_range = 30.00
      • Set missile_speed = 12.50
      • Set missile_stop = False
      • Set missile_timer = 0.00
      • Unit - Create 1 Kunai for Player at TempLoc[4] facing missile_angle degrees
      • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Unit - Add Crow Form to (Last created unit)
      • Unit - Remove Crow Form from (Last created unit)
      • Unit Group - Add (Last created unit) to missile_move_group
      • Trigger - Turn on Movement loop <gen>
      • Set unit[1] = (Last created unit)
      • Custom script: set udg_key[0] = GetHandleId(udg_unit[1])
      • Hashtable - Save missile_angle as (Key angle) of key[0] in missile_hash
      • Hashtable - Save Handle Ofunit[0] as (Key caster) of key[0] in missile_hash
      • Hashtable - Save missile_damage as (Key damage) of key[0] in missile_hash
      • Hashtable - Save missile_distance as (Key distance) of key[0] in missile_hash
      • Hashtable - Save missile_health as (Key health) of key[0] in missile_hash
      • Hashtable - Save missile_homing as (Key homing) of key[0] in missile_hash
      • Hashtable - Save missile_knockback as (Key knockback) of key[0] in missile_hash
      • Hashtable - Save (X of TempLoc[0]) as (Key x) of key[0] in missile_hash
      • Hashtable - Save (Y of TempLoc[0]) as (Key y) of key[0] in missile_hash
      • Hashtable - Save missile_range as (Key range) of key[0] in missile_hash
      • Hashtable - Save missile_speed as (Key speed) of key[0] in missile_hash
      • Hashtable - Save missile_stop as (Key stop) of key[0] in missile_hash
      • Hashtable - Save Handle Ofmissile_target as (Key target) of key[0] in missile_hash
      • Hashtable - Save missile_timer as (Key time) of key[0] in missile_hash
      • Set missile_target = No unit
      • Custom script: call RemoveLocation(udg_TempLoc[0])
      • Custom script: call RemoveLocation(udg_TempLoc[1])
      • Custom script: call RemoveLocation(udg_TempLoc[2])
      • Custom script: call RemoveLocation(udg_TempLoc[3])
 
Level 7
Joined
Nov 19, 2015
Messages
283
I had a quick look in the trigger and I think you didn't follow the equation correctly. What is TempLoc[4] and why does it used an uninitialized variable (missile_angle). Your trigger has very very little readability so I can't help you enough.

Sorry, It messy, I was going to try make it all into one line instead of using heaps of set real[n]. I was playing around with the trigger and forgot to change it back when I posted it.

  • Kunai
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Throw Kunai
      • (Target item of ability being cast) Equal to No item
    • Actions
      • Set Player = (Owner of (Triggering unit))
      • Set unit[0] = (Triggering unit)
      • Set TempLoc[0] = (Position of unit[0])
      • Set TempLoc[1] = (Target point of ability being cast)
      • Set unit[1] = (Target unit of ability being cast)
      • Set missile_target = No unit
      • Set missile_target = unit[1]
      • Set TempLoc[2] = (Position of unit[1])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • UnitMoving[(Custom value of missile_target)] Equal to True
          • missile_target Not equal to No unit
        • Then - Actions
          • -------- Law of Cosine --------
          • -------- Angle A --------
          • Set real[0] = ((Facing of missile_target) + (Angle from TempLoc[0] to TempLoc[2]))
          • -------- Distance --------
          • Set real[1] = ((Distance between TempLoc[0] and TempLoc[2]) - 50.00)
          • -------- Missile speed --------
          • Set real[2] = 1250.00
          • -------- -2*D*Tspeed*cos(A) --------
          • Set real[3] = ((-2.00 x real[1]) x ((Current movement speed of missile_target) x (Cos(real[0]))))
          • -------- 4*D*D*((Mspeed^2)-(Tspeed^2)) --------
          • Set real[4] = ((4.00 x (real[1] x real[1])) x ((real[2] x real[2]) - ((Current movement speed of missile_target) x (Current movement speed of missile_target))))
          • -------- 2*((Mspeed^2)-(Tspeed^2)) --------
          • Set real[5] = (2.00 x ((real[2] x real[2]) - ((Current movement speed of missile_target) x (Current movement speed of missile_target))))
          • -------- Final --------
          • Set real[6] = ((real[3] + (Square root(((real[3] x real[3]) + real[4])))) / real[5])
          • Set real[7] = ((real[3] - (Square root(((real[3] x real[3]) + real[4])))) / real[5])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • real[6] Less than or equal to real[7]
              • real[6] Greater than or equal to 0.00
            • Then - Actions
              • Set real[8] = real[6]
            • Else - Actions
              • Set real[8] = real[7]
          • Set TempLoc[3] = (TempLoc[2] offset by ((Current movement speed of missile_target) x real[8]) towards (Facing of missile_target) degrees)
        • Else - Actions
          • Set TempLoc[3] = TempLoc[2]
      • Set missile_angle = (Angle from TempLoc[0] to TempLoc[3])
      • Set TempLoc[4] = (TempLoc[0] offset by 50.00 towards missile_angle degrees)
Temp_Loc[4] is the position where the missile is spawned. That's why I subtract 50 from the distance between the caster and target. Even when I fixed the distance it made no difference in the accuracy.

Edit: I think I may be doing the distance thing wrong
 
Last edited:
Status
Not open for further replies.
Top