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

Simple 2D traceline function

Status
Not open for further replies.
Level 11
Joined
Aug 1, 2009
Messages
963
I made a better (and more efficient) traceline system for my map that doesn't loop a hundred times.

Because lots of people are probably using the other kind of traceline, which is annoyingly inefficient, I decided to share this with you! Hooray!

Now, notice that this doesn't include height detection or a Z axis, mostly because those things are irrelevant in the project I created. However, a 3 dimesional line is nothing more than 3 2 dimensional lines, one on the x/y plane, one on the y/z plane, and one on the x/z plane, so it shouldn't be too difficult to figure out. Additionally, what is (are?) terrain height and cliffs but a complex 2 dimensional piecewise function?

[TRIGGER=Tracelines]Tracelines
Options: Function
Return Type: Unit
Parameters
distance = 0.0 <Real>
StartPoint = No Point <Point>
SourceUnit = No Unit <Unit>
Angle = 0.0 <Real>
Local Variables
a = (-Sin(Angle)) <Real>
b = (Cos(Angle)) <Real>
g = (Any units in (Region((StartPoint offset by (distance / 2.0) towards Angle degrees), (distance / 2.0))) owned by player Any Player matching Excluded: Psionic, Missile, Dead, Hidden, with at most Any Amount) <Unit Group>
g2 = (Empty unit group) <Unit Group>
u = No Unit <Unit>
u2 = No Unit <Unit>
x = 0.0 <Real>
y = 0.0 <Real>
x1 = (X of StartPoint) <Real>
y1 = (Y of StartPoint) <Real>
Actions
------- Coded by mrzwach, alias fernsauce.
Unit Group - Remove SourceUnit from g //This is simply so that it cannot return the unit from which the line is being traced.
Unit Group - For each unit u in g do (Actions)
Actions
Variable - Set x = ((X of (Position of u)) - x1) //Because my formula for the line being traced is ax+by=0, the origin (and source position) is (0, 0).
Variable - Set y = ((Y of (Position of u)) - y1) //Since the actual location in the coordinate grid is not (0, 0) I must adjust the coordinates of units being checked.
General - If (Conditions) then do (Actions) else do (Actions)
If
(u Radius (Current)) >= (Abs(((a * x) + (b * y))) //Derived from distance to line formula
Then
Unit Group - Add u to g2
Else
General - If (Conditions) then do (Actions) else do (Actions)
If
(Number of Living units in g2) == 0
Then
General - Return No Unit
Else
General - While (Conditions) are true, do (Actions)
Conditions
(Number of Living units in g2) >= 1
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
(Number of Living units in g2) > 1
Then
Variable - Set u = (Unit 1 from g2)
Variable - Set u2 = (Unit 2 from g2)
General - If (Conditions) then do (Actions) else do (Actions)
If //This part is to check which unit is closer, so that it can return the closest unit.
(Distance between (Position of u) and StartPoint) >= (Distance between StartPoint and (Position of u2))
Then
Unit Group - Remove u from g2
Else
Unit Group - Remove u2 from g2
Else
Variable - Set u = (Unit 1 from g2)
Unit Group - Remove u from g2
General - Return u
General - Return No Unit //The only reason for this part is that SC2 will pop up with a syntax error otherwise, even if it is impossible

[/TRIGGER]
 
Last edited:
Level 12
Joined
Apr 15, 2008
Messages
1,063
The usage of "divisor" is unnecessary, it is always equal to distance. ( (-sin,cos) vector has length of 1, you multiply it by distance )
Also, you don't even need to multiply it by distance, just use the (-sin, cos), and you won't need to divide it again.

And since this is very useful, I suggest you improve it to 3D (it's not necessary to use 2 additional lines, just test the height of the unit and the height the 3D line should have at that point), write some usage information and post it as tutorial asap, before people start using the 100 loop version :grin:
 
Last edited:
Level 11
Joined
Aug 1, 2009
Messages
963
Basically, its a function that traces a line from a starting point to an end point, and then returns the first unit it runs into on the line. I use it so that I can pick targets for a line-attack ability for a project of mine, many other people use various functions like this for figuring out if the player is aiming at something.

Also, M0RT, bit lazy atm, lol. I'm thinking when I do do it I should just divide up the map into a grid (because thats how it works normally) and make a 2D array that has the cliff level of each point. Then, when calculating the traceline I figure out all the spaces it would pass through, and if there is a change in height I can tell if it would block the line.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,180
This could still be hevilly optimized by reducing unnescescary object creation and by reducing group scope size of a single group instead of using 2 groups.

Additionally you keep track of the nearest unit instead

Also you should comment your maths, it is very strange what you are doing.
 
Level 11
Joined
Aug 1, 2009
Messages
963
Why?
The reason for a and b is because they are coefficients for a line, standard form for line is ax+by+c=0
g is for group, u is for unit, x/y is for the x/y coordinates.

Don't really see any problem with that, seems pretty straightforward to me.
 
Level 8
Joined
Aug 2, 2006
Messages
346
Also what you need to do is code your own distance function that leaves off the square root. Since you don't actually need the square root, and since square roots are very costly computation-wise, just leave it off the equation. You'll be dealing with square distances, but everything would still sort the same way.
 
Status
Not open for further replies.
Top