- Joined
- Jul 25, 2014
- Messages
- 490
How to use coordinates instead of points in GUI
General description:
Most GUI Trigger users use points(locations) in their code to get a point in the map, mostly for moving, creating effects, checking valid points and so on. And they are probably frustrated with them because they're not efficient, full of lags and have to be cleaned by a custom script after usage.
JASS doesn't have such problems because they use coordinates. This tutorial helps you convert your coding full of points into full of coordinates.
NOTE! This tutorial is reliant on custom script usage. If you're just starting to learn triggers, it is recommended to wait until using them, unless they're necessary. There will be a lot of udg_ prefixes (declaration of a global GUI variable).
Why coordinates?
Because unlike points, they ARE efficient. They don't need to be cleaned up because they're Real type variable values. They are also more efficient in terms of speed and moving units with coordinates using SetUnitX/Y do not interrupt orders. It can be chosen to interrupt them using SetUnitPosition which also take coordinates as arguments.
Practical usage
-------------------------------------------------------------
For practical usage, one should have at least two Real type variables, let's call them x and y. Let's start off with something simple like creating a special effect at the target point of ability being cast, using coordinates and a simple Thunder Clap effect.
-------------------------------------------------------------
Moving on to a little more sophisticated function with coordinates we have distances. Distances are calculated with the vector formula from your daily math struggles. It has to have at least two sets of coordinates (for the first point and for the second point). Let's give it a try!
-------------------------------------------------------------
And now moving on to an example usage, for example lets take a spell. I'm going to do it with Dynamic Indexing since, in my opinion, it is the most common method for GUI users to make their spells or triggers MUI. If you don't know what it does, make sure to read up on PurgeandFire's tutorial about Dynamic Indexing.
A test spell that spams messages on the screen whenever the distance between the caster and the target is greater than 300 and pulls the target to the caster, not interrupting orders. If it is lower, it will say "Hello good sir" and end the spell. And it's done with calculating the distance with coordinates.
-- There's nothing to breakdown anymore, it is that simple! Now you can use coordinates instead of points in your triggers! For the SetUnitX/SetUnitY/Atan2 angle movement make sure to visit the About Movement tutorial by D4RK_G4ND4LF, it is extremely descriptive.
Further notes:
This can be done with local variables instead of using global ones when declaring coordinates, but this would push the user forward to using JASS over GUI. It can be a nice waypoint when it is done with globals -- it is not that scary.
Drop feedback!
@Moderators: If there were major points/minor typos that I missed out, let me know.
@Users: If the information was still not quite clear to you, let me know, I will update the tutorial to be as descriptive as possible.
General description:
Most GUI Trigger users use points(locations) in their code to get a point in the map, mostly for moving, creating effects, checking valid points and so on. And they are probably frustrated with them because they're not efficient, full of lags and have to be cleaned by a custom script after usage.
JASS doesn't have such problems because they use coordinates. This tutorial helps you convert your coding full of points into full of coordinates.
NOTE! This tutorial is reliant on custom script usage. If you're just starting to learn triggers, it is recommended to wait until using them, unless they're necessary. There will be a lot of udg_ prefixes (declaration of a global GUI variable).
Why coordinates?
Because unlike points, they ARE efficient. They don't need to be cleaned up because they're Real type variable values. They are also more efficient in terms of speed and moving units with coordinates using SetUnitX/Y do not interrupt orders. It can be chosen to interrupt them using SetUnitPosition which also take coordinates as arguments.
Practical usage
-------------------------------------------------------------
For practical usage, one should have at least two Real type variables, let's call them x and y. Let's start off with something simple like creating a special effect at the target point of ability being cast, using coordinates and a simple Thunder Clap effect.
-
Special effect usage
-
Events
-
Unit - A unit Starts the effect of an ability
-
-
Conditions
-
(Ability being cast) Equal to Doom
-
-
Actions
-
Custom script: set udg_x = GetSpellTargetX()
-
Custom script: set udg_y = GetSpellTargetY()
-
Custom script: call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl", udg_x, udg_y))
-
-------- Doesn't have to be cleaned! --------
-
-
- First line is to set the Target Point Of Ability Being Cast X coordinate. Notes - this doesn't actually use a point.
- Second line is for the same reason, just with an Y coordinate.
- This is where it gets a little tricky for an ordinary user. We instantly destroy the effect created because if we don't it will leak, obviously. Inside the second brackets, the first argument is for the file path. Note that it has to be done with double backwards slashes, that's just how the compiler gets that it's a filepath. The second/third arguments are for the wanted X and Y coordinates. We use the ones we set earlier.
-------------------------------------------------------------
Moving on to a little more sophisticated function with coordinates we have distances. Distances are calculated with the vector formula from your daily math struggles. It has to have at least two sets of coordinates (for the first point and for the second point). Let's give it a try!
-
Distance usage
-
Events
-
Unit - A unit Starts the effect of an ability
-
-
Conditions
-
(Ability being cast) Equal to Doom
-
-
Actions
-
Set Caster = (Triggering unit)
-
Set Target = (Target unit of ability being cast)
-
Custom script: set udg_x = GetUnitX(udg_Caster)
-
Custom script: set udg_x = GetUnitY(udg_Caster)
-
Custom script: set udg_x2 = GetUnitX(udg_Target)
-
Custom script: set udg_y2 = GetUnitY(udg_Target)
-
-------- The following two lines are optional, they exist just to ensure readability. --------
-
Set dx = (x2 - x)
-
Set dy = (y2 - y)
-
-------- Let's calculate! --------
-
Set Distance = (Square root(((dx x dx) + (dy x dy))))
-
-
- The first 6 lines are already known to us so I'll just skip them.
- dx and dy are both real values which calculate the distance on their respective axis. They can be skipped and directly be used in the distance formula, but it helps to read and edit if they are done seperately. Doesn't matter from which coordinate you subtract the other, in the end it is squared and the minus sign is gone (if it was there in the first place).
- The Distance is calculated by using a simple formula (Pythagoras Theorem) by using the two axis distances we set before.
-------------------------------------------------------------
And now moving on to an example usage, for example lets take a spell. I'm going to do it with Dynamic Indexing since, in my opinion, it is the most common method for GUI users to make their spells or triggers MUI. If you don't know what it does, make sure to read up on PurgeandFire's tutorial about Dynamic Indexing.
A test spell that spams messages on the screen whenever the distance between the caster and the target is greater than 300 and pulls the target to the caster, not interrupting orders. If it is lower, it will say "Hello good sir" and end the spell. And it's done with calculating the distance with coordinates.
-
Practical Usage
-
Events
-
Unit - A unit Starts the effect of an ability
-
-
Conditions
-
(Ability being cast) Equal to Doom
-
-
Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
MaxIndex Equal to 0
-
-
Then - Actions
-
Trigger - Turn on Practical Usage loop <gen>
-
-
Else - Actions
-
-
-------- Setting up needed variables. --------
-
Set MaxIndex = (MaxIndex + 1)
-
Set Caster[MaxIndex] = (Triggering unit)
-
Set Target[MaxIndex] = (Target unit of ability being cast)
-
Custom script: set udg_x = GetUnitX(udg_Caster[udg_MaxIndex])
-
Custom script: set udg_x = GetUnitY(udg_Caster[udg_MaxIndex])
-
Custom script: set udg_x2 = GetUnitX(udg_Target[udg_MaxIndex])
-
Custom script: set udg_y2 = GetUnitY(udg_Target[udg_MaxIndex])
-
-------- Setting up the angle, (from target to caster) explained later. --------
-
Custom script: set udg_Angle[udg_MaxIndex] = Atan2(udg_x2 - udg_x, udg_y2 - udg_y)
-
-------- Calculating the distance. --------
-
Set dx = (x2 - x)
-
Set dy = (y2 - y)
-
Set Distance[MaxIndex] = (Square root(((dx x dx) + (dy x dy))))
-
-
-
Practical Usage loop
-
Events
-
Time - Every 0.03 seconds of game time
-
-
Conditions
-
Actions
-
For each (Integer CurrentIndex) from 1 to MaxIndex, do (Actions)
-
Loop - Actions
-
-------- Setting up needed variables. --------
-
Custom script: set udg_x = GetUnitX(udg_Caster[udg_CurrentIndex])
-
Custom script: set udg_x = GetUnitY(udg_Caster[udg_CurrentIndex])
-
Custom script: set udg_x2 = GetUnitX(udg_Target[udg_CurrentIndex])
-
Custom script: set udg_y2 = GetUnitY(udg_Target[udg_CurrentIndex])
-
-------- Calculating the distance. --------
-
Set dx = (x2 - x)
-
Set dy = (y2 - y)
-
Set Distance[MaxIndex] = (Square root(((dx x dx) + (dy x dy))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Distance[MaxIndex] Greater than or equal to 300.00
-
-
Then - Actions
-
-------- Moving the unit using SetUnitX/SetUnitY. --------
-
Custom script: set udg_Angle[udg_CurrentIndex] = Atan2(udg_x2 - udg_x, udg_y2 - udg_y)
-
Custom script: call SetUnitX(udg_Target[udg_CurrentIndex], udg_x2 + 5.00 * Cos(udg_Angle[udg_CurrentIndex]))
-
Custom script: call SetUnitY(udg_Target[udg_CurrentIndex], udg_y2 + 5.00 * Sin(udg_Angle[udg_CurrentIndex]))
-
Game - Display to (All players) the text: Come back here!
-
-
Else - Actions
-
Game - Display to (All players) the text: Hello good sir!
-
-------- Deindexing. --------
-
Set Caster[CurrentIndex] = Caster[MaxIndex]
-
Set Target[CurrentIndex] = Target[MaxIndex]
-
Set Distance[CurrentIndex] = Distance[MaxIndex]
-
Set CurrentIndex = (CurrentIndex - 1)
-
Set MaxIndex = (MaxIndex - 1)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
MaxIndex Equal to 0
-
-
Then - Actions
-
Trigger - Turn off Practical Usage loop <gen>
-
-
Else - Actions
-
-
-
-
-
-
-------- Done! --------
-
-
Further notes:
This can be done with local variables instead of using global ones when declaring coordinates, but this would push the user forward to using JASS over GUI. It can be a nice waypoint when it is done with globals -- it is not that scary.
Drop feedback!
@Moderators: If there were major points/minor typos that I missed out, let me know.
@Users: If the information was still not quite clear to you, let me know, I will update the tutorial to be as descriptive as possible.
Last edited: