| 02-16-2007, 08:47 AM | #2 |
If you're going to start using movement effects you should really not use polarproject unless you like lag, instead manually manipulate the x and y values of the units using sin and cos... newx = currentx + Cos(angle*bj_DEGTORAD)*distance newy = currenty + Sin(angle*bj_DEGTORAD)*distance You can use it in conjunction with my function to check pathability and map boundries if you want: Code:
function CheckPathability takes unit u, real x, real y returns boolean
local real ox = GetUnitX(u)
local real oy = GetUnitY(u)
if x > MAX_X then
return false
elseif x < MIN_X then
return false
if y > MAX_Y then
return false
elseif y < MIN_Y then
return false
endif
call SetUnitX(u, -9472.)
call SetUnitY(u, 9216.)
call SetUnitPosition(PATHUNIT, x, y)
set x = GetUnitX(PATHUNIT)-x
set y = GetUnitY(PATHUNIT)-y
call SetUnitX(PATHUNIT, -9472.)
call SetUnitY(PATHUNIT, 9216.)
call SetUnitX(u, ox)
call SetUnitY(u, oy)
return x*x+y*y <= 100.
endfunction-9472, 9216 is a chosen safespot on my map where units are moved to temporarily during this function and where the PATHUNIT is stored. MIN_X, MIN_Y and so on are the map boundries. It's best if you actually place the map boundry numbers directly into the function rather than using a variable since it will be slightly faster. PATHUNIT is a global unit variable containing a ground unit with 32 collision radius and no model. Do not create and destroy a unit because this function is designed to be as speedy as possible and could wind up executing it hundreds of times per second. Also rapidly creating/destroying handles increases WC3's memory usage substantially. Really a function like this is the only way to check if another unit gets in the way while you're moving around units with SetUnitX and SetUnitY unless you want the horrible lag of making WC3's check its pathing map. Code:
function AngleBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real
return Atan2((y2-y1),(x2-x1))*bj_RADTODEG
endfunctionso to put it all together... Code:
set angle = AngleBetweenPointsXY(soulwallx, soulwally, unitx, unity) //or just use the math
set newx = currentx + Cos(angle*bj_DEGTORAD)*distance
set newy = currenty + Sin(angle*bj_DEGTORAD)*distance
if CheckPathability(u, newx, newy) then
call SetUnitX(u, x)
call SetUnitY(u, y)
endif |
| 02-16-2007, 10:50 AM | #3 | |
Quote:
You are doing the same as polar projection. Polar Projection method: JASS:function PolarProjectionBJ takes location source, real dist, real angle returns location local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD) local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD) return Location(x, y) endfunction Your method: JASS:newx = currentx + Cos(angle*bj_DEGTORAD)*distance newy = currenty + Sin(angle*bj_DEGTORAD)*distance Pretty much the same. |
| 02-16-2007, 12:28 PM | #4 |
It is not the same, since you are constantly creating locations just do remove them later. But It is not like it would really lag that much... |
| 02-16-2007, 03:08 PM | #5 | |
Quote:
I mean the method is literally the same. Calculation of the new x and y is the same in both examples. |
| 02-16-2007, 10:46 PM | #6 |
Of course the calculation of X and Y is the same in both examples. After all, trig is required either way to solve that problem. Vexorian is right in that this ability would not lag very much by itself. But it's important to get started on good coding practices for movement effects early. If he starts adding more abilities like this the unnecessary function calls and location usage will eventually take their toll on performance. It can make a very noticable difference in a "real map." The worst thing is the continuous creation and destruction of handles (the locations) since that will eat both performance and memory. Also, there was no bound checking or collision checking with other units in his example; I was showing him how to do that without causing lag. Upon looking at your code a little more closely: set D = Distance (X1, Y1, X2, Y2) set P2 = PolarProjectionBJ(P, 90.00-D, (bj_RADTODEG * Atan2(Y2-Y1, X2-X1))) If you do that you aren't going to "push" anything back, but rather you're going to instantly teleport them out of the radius of the pushback. You should use a fixed speed like 5 or something if you want a real pushback. Also I don't see where you even used getreverseangle since it's commented out, but if you did use it, it would cause your unit to flip back and forth like you showed in your pictures. So there's no need for that function here. |
| 02-17-2007, 01:44 AM | #7 | |
Quote:
Get_Reverse_Angle() was a function I was using earlier in an attempt to rectify my problem. At this point, I am not using it. |
| 02-18-2007, 03:34 AM | #8 |
I just thought it might look cooler if they were pushed back. It's hard to tell what could be wrong with your code. Sometimes if you start over using a cleaner methodology the problem will correct itself. |
| 02-20-2007, 10:20 PM | #9 |
I'm baffled. The code still moves units in a somewhat random direction (though they do eventually get moved far enough away) at an extremely slow rate! The units will move barely any distance when the trigger runs, though they should instantly be moved outside of the radius... JASS:function AngleBetweenPointsXY takes real X1, real Y1, real X2, real Y2 returns real return Atan2((Y2-Y1),(X2-X1))*bj_RADTODEG endfunction function Distance takes real X1, real Y1, real X2, real Y2 returns real return SquareRoot( (X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2) ) endfunction function Souls_Filter takes nothing returns boolean return GetUnitTypeId(GetFilterUnit()) == 'h000' endfunction function Souls_Filter_Opposite takes nothing returns boolean return GetUnitTypeId(GetFilterUnit()) != 'h000' endfunction function Souls_Set_Unit_XY takes unit Soul, unit U returns nothing local real X1 = GetUnitX(Soul) local real Y1 = GetUnitY(Soul) local real X2 = GetUnitX(U) local real Y2 = GetUnitY(U) local real D = Distance(X1, Y1, X2, Y2) local real X3 = X2 + Cos(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) local real Y3 = Y2 + Sin(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) call SetUnitX(U, X3) call SetUnitY(U, Y3) call BJDebugMsg("Moved") endfunction function Trig_Periodic_Move_Away_Actions takes nothing returns nothing local boolexpr B = Condition(function Souls_Filter) local boolexpr B2 = Condition(function Souls_Filter_Opposite) local group G = GetUnitsInRectMatching(GetPlayableMapRect(), B) local group G2 = CreateGroup() local unit Soul local unit U local real X local real Y // local real X1 // local real Y1 // local real X2 // local real Y2 // local real X3 // local real Y3 // local real D loop set Soul = FirstOfGroup(G) exitwhen Soul == null set X = GetUnitX(Soul) set Y = GetUnitY(Soul) call GroupEnumUnitsInRange(G2, X, Y, 300.00, B2) loop set U = FirstOfGroup(G2) exitwhen U == null call Souls_Set_Unit_XY(Soul, U) // set X1 = GetUnitX(Soul) // set Y1 = GetUnitY(Soul) // set X2 = GetUnitX(U) // set Y2 = GetUnitY(U) // set D = Distance(X1, Y1, X2, Y2) // set X3 = X2 + Cos(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) // set Y3 = Y2 + Sin(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) // call SetUnitX(U, X3) // call SetUnitY(U, Y3) // call BJDebugMsg("Moved") call GroupRemoveUnit(G2, U) endloop call GroupRemoveUnit(G, Soul) endloop call DestroyGroup(G) call DestroyGroup(G2) call DestroyBoolExpr(B) call DestroyBoolExpr(B2) set U = null set Soul = null set G = null set G2 = null set B = null set B2 = null endfunction //=========================================================================== function InitTrig_Periodic_Move_Away takes nothing returns nothing set gg_trg_Periodic_Move_Away = CreateTrigger( ) call TriggerRegisterTimerEventPeriodic( gg_trg_Periodic_Move_Away, 0.5 ) call TriggerAddAction( gg_trg_Periodic_Move_Away, function Trig_Periodic_Move_Away_Actions ) endfunction |
| 02-21-2007, 06:31 AM | #10 |
Ah! I've found my error. I forgot my bj_DEGTORAD... Silly me. grim001, I appreciate the help; and you too, The)TideHunter(. Rep'd |
| 02-21-2007, 08:35 AM | #11 |
You also need to move the distance outside of the parenthesis or you're still going to get incorrect results |
| 02-21-2007, 12:01 PM | #12 |
Grim's right. JASS:local real X3 = X2 + Cos(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) local real Y3 = Y2 + Sin(AngleBetweenPointsXY(X1, Y1, X2, Y2)*(300.00-D)) Should be -- JASS:local real X3 = X2 + (300.00-D)*Cos(AngleBetweenPointsXY(X1, Y1, X2, Y2)) local real Y3 = Y2 + (300.00-D)*Sin(AngleBetweenPointsXY(X1, Y1, X2, Y2)) |
| 02-21-2007, 03:31 PM | #13 |
but now you forgot the bj_DEGTORAD |
| 02-21-2007, 04:31 PM | #14 |
Most normal people put that in the AngleBetweenPointsXY(..) function call. |
| 02-21-2007, 04:53 PM | #15 |
nope, what is in the anglebetweenpoints is bj_RADTODEG. When it calculates the angle it is in radians then it is converted to degrees before being returned by the fucntion then you have to convert it back to radians again for newx/newy calculation if you inline the math the RADTODEG and DEGTORAD can cancel out. |
