HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Parabola along the ground??

03-07-2006, 08:57 PM#1
emjlr3
well, what I am trying to do is quickly move a unit along the ground in a parabola like thing, ex.

O Target of Ability
I
I
I ** (It won't post how I want to show it, but I think you get the idea)
I but basically a sideways parabola, like a jump, but along the ground on the x/y axis
I so instead of going in a straight line to the target, you go at an arc outward
O Caster Position

any ideas or thoughts of how to accomplish this movement?
03-07-2006, 09:01 PM#2
Anitarf
Hmm, you could define and calculate the points of the parabola in an independant x/y system and then rotate the points around the origin to the angle between the caster and the target.
03-07-2006, 09:13 PM#3
shadow1500
Collapse JASS:
function JumpParabola takes real dist, real maxdist,real curve returns real
    local real t = (dist*2)/maxdist-1
    return (-t*t+1)*(maxdist/curve)
endfunction
there, curve must be a number between 1 and 2 (i suggest 1.8)
dist is the current distance and maxdist is the maximum distance
03-08-2006, 12:12 AM#4
emjlr3
could you show me how to use this, I am a little confused here

i have to keep checking the guys distance to where he is trying to get?

so distance should always be something like:

DistanceBetweenPoints(GetUnitLoc(u),GetSpeelTargetLoc())

max distance would be the distane between unit location at spell effect and target

and real curve is what you suggested, 1.8, what exactly is the real that this gives me? the location to move the unit to or what? and how exactly could I use it to not make my guy jump, but to have him go how I want it to?

Quote:
Hmm, you could define and calculate the points of the parabola in an independant x/y system and then rotate the points around the origin to the angle between the caster and the target.

im lost


again incase there is any misunderstanding this is what I am looking for ( there is no change in the units fly height), this shows the movement wanted from the caster:

03-08-2006, 12:47 AM#5
shadow1500
Oh, i dont think u can do that like u wanted, what ur trying to do is complicated.. i dont know how to do this, and i dont know if the function is going to help u, but ill explain it anyway,

u use a timer to move the unit, from position 1 to position 2, the distance between position 1 and 2 is a constant and is used for maxdist for the function
the current distance from position 1 (or 2, w/e u pick result is the same anyway) to the unit is dist, so u need to calculate it everytime the timer is ran.
and curve.. hard to explain, so here's a pic
Zoom (requires log in)

i never even learned trigonometry yet so dont blame me for the lack of skill.. i searched in google for a graphing program and started adjusting the equation until i got a parabola that worked for warcraft 3.
Attached Images
File type: pngcurves1bf.png (2.1 KB)
03-08-2006, 02:20 AM#6
Vexorian
You should probably take a look into bezier curves with a bezier curve you can make a curve like movement

let's say that you have 2 variables a and b

a starts on 0 and will end in 1.
b starts on 1 and will end in 0 (as a matter of fact b=1-a)

You also need points A,B and C:

Zoom (requires log in)

You can make A be the initial position of the caster and C the target position, B will determine the kind of curve

A=(Ax,Ay)
B=(Bx,By)
C=(Cx,Cy)

Then you should use these formulas to get the coordinates of a new point depending on different values from a=0 to a=1 (note that b=1-a)

Code:
X(a) = Ax·a² + Bx·2·a·b + Cx·b²
Y(a) = Ay·a² + By·2·a·b + Cy·b²
Attached Images
File type: gifcurveQuadratic[1].gif (1.4 KB)
03-08-2006, 05:21 AM#7
emjlr3
aight Vex ill give it a whirl, though I dont fully understand it all :(

and Shadow, again, what is the real that you are given with the equation? is that supposed to be the unit fly height(z), since you are manually setting the movement along the x/y ( jsut wondering for future jump spells)

just typing this all in as I go along:

so, we got point A,B, and C, will add more as I go

A = caster position
B = target position
C = PolarProjectionBJ(A,SquareRoot(((DistanceBetweenPoints(A,B)/2)^2)+200^2),45) -----200 just as a set number to work from now

now as far as moving my unit, i am a little lost

do I set a = 0 and b = 1

then each run of the trigger set a = a + .01 and b = b - .01, and run the function 100 times to get the curve, setting my x and y coordinates using your equations?
03-08-2006, 08:13 AM#8
Anitarf
Correct, as vex said, a goes from 0 to 1.
03-08-2006, 07:40 PM#9
emjlr3
well, i tried, and failed misserably, after some debugging it seems that the dummy unit is created at the ending point, and slowly goes backwards towards the starting point( if I remove the part for destroying the timer if the unit is near the ending point), so if I changed it to a = 1 and b = 0, and subtract from a and add to b, it creates the dummy at the start point, and moves it very slowly to the end point( lowering the trigger run speed to .007 solves this and makes it go at the speed wanted) , no curve, just a straight line... :( , anywho, here is what I got

Collapse JASS:
function BezierCurve takes real Ax, real Ay, real Bx, real By, real Cx, real Cy, real a, real b returns location
    local real x = (Ax*(a*a)) + (Bx*2*a*b) + (Cx*(b*b))
    local real y = (Ay*(a*a)) + (By*2*a*b) + (Cy*(b*b)) // use equations suggested to get points...btw how do I remove location leak here, I tried and it gave me errors
    local location l = Location(x,y)
    return l    
endfunction

function ShadowBreeze_Walk takes nothing returns nothing
    local timer t = GetExpiredTimer()       
    local real x1 = GetHandleReal(t,"x1")
    local real y1 = GetHandleReal(t,"y1")
    local real x2 = GetHandleReal(t,"x2")
    local real y2 = GetHandleReal(t,"y2")
    local real x3 = GetHandleReal(t,"x3")
    local real y3 = GetHandleReal(t,"y3")
    local real a = GetHandleReal(t,"a")
    local real b = GetHandleReal(t,"b")
    local location l = BezierCurve(x1,y1,x3,y3,x2,y2,a,b) //Get position using equations   
    
    call SetUnitPositionLoc(GetHandleUnit(t, "dum"),l)    
    call SetUnitAnimation(GetHandleUnit(t, "dum"), "walk")
    if IsUnitInRangeXY(GetHandleUnit(t, "dum"),x2,y2, 100) or GetUnitState(GetHandleUnit(t, "dum"), ConvertUnitState(0)) <= 0 then // end of dummy is near end point
        call KillUnit(GetHandleUnit(t, "dum"))
        call RemoveUnit(GetHandleUnit(t, "dum"))
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    call SetHandleReal(t,"a",a + .01) // make a go from 0 - 1 and b from 1-0 like Vex said
    call SetHandleReal(t,"b",b - .01)

    set t = null
    call RemoveLocation(l)
    set l = null
endfunction

function ShadowBreeze_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()        
    local timer t = CreateTimer()   
    local real x1 = GetUnitX(u)  // reals for point A
    local real y1 = GetUnitY(u)
    local location l = GetSpellTargetLoc()     
    local real x2 = GetLocationX(l)  // reals for Point C
    local real y2 = GetLocationY(l)     
    local unit dum = CreateUnit(p, 'n000', x1, y1, a)
       

    local real dist = SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))/2
    local real dist2 = SquareRoot((dist*dist)+(200*200))   
    // used Pythagoreaum Thereom to get location of point B
    local real x3 = x1 + dist2 * Cos(a * bj_DEGTORAD)  // Reals for point B
    local real y3 = y1 + dist2 * Sin(a * bj_DEGTORAD)
    call SetHandleReal(t,"x3",x3) 
    call SetHandleReal(t,"y3",y3)
    call SetHandleReal(t,"x1",x1) 
    call SetHandleReal(t,"y1",y1)
    call SetHandleReal(t,"a",0) // set a to 0 and b to 1 like Vex said to start with
    call SetHandleReal(t,"b",1)   
   
    call UnitApplyTimedLife(dum, 'BTLF', 2)    
    call SetHandleReal(t,"x2",x2)
    call SetHandleReal(t,"y2",y2)
    call SetHandleHandle(t, "dum", dum)    
    
    call SetUnitTimeScalePercent(dum, 10000)
    call SetUnitAnimation(dum, "walk")
    call TimerStart(t, .025, true, function ShadowBreeze_Walk)
    call TriggerSleepAction(0)
    call MoveUnitToPolarProjection(u,SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))+50, a)    
    call SetUnitFacing(u,bj_RADTODEG * Atan2(GetUnitY(u)-y2,GetUnitX(u)-x2)) // this is unit targetable, so gotta move the caster to the target
    
    set t = null
    set u = null
    call RemoveLocation(l)
    set l = null
    set dum = null
endfunction

Vex.... helpppp...
03-08-2006, 09:00 PM#10
Vexorian
From what I've seen is that point A and B should be calculated when the spell begins, not every time (should stay constant) otherwise it screws the effect.

I am gonna check the details later
03-09-2006, 12:41 AM#11
emjlr3
ouch???

I believe all teh points are calculated at the beggining of the spell

Collapse JASS:
call SetHandleReal(t,"x3",x3) 
call SetHandleReal(t,"y3",y3)
call SetHandleReal(t,"x1",x1) 
call SetHandleReal(t,"y1",y1)
call SetHandleReal(t,"x2",x2)
call SetHandleReal(t,"y2",y2)

and they are never changed throughout the spell...
03-09-2006, 01:48 AM#12
Vexorian
Collapse JASS:
//function BezierCurve takes real Ax, real Ay, real Bx, real By, real Cx, real Cy, real a, real b returns location
//    local real x = (Ax*(a*a)) + (Bx*2*a*b) + (Cx*(b*b))
//    local real y = (Ay*(a*a)) + (By*2*a*b) + (Cy*(b*b)) // use equations suggested to get points...btw how do I remove location leak here, I tried and it gave me errors
//    local location l = Location(x,y)
//    return l    
//endfunction
//The answer is to do not use a function, or use 2 functions, or even one function because the formula is the same for x and y.
//Or you can make it take a location and use MoveLocation

function BezierCurveValue takes real a, real b, real A, real B, real C  returns real
    return A*a*a+2*B*a*b+C*b*b
endfunction


function ShadowBreeze_Walk takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real x1 = GetHandleReal(t,"x1")
    local real y1 = GetHandleReal(t,"y1")
    local real x2 = GetHandleReal(t,"x2")
    local real y2 = GetHandleReal(t,"y2")
    local real x3 = GetHandleReal(t,"x3")
    local real y3 = GetHandleReal(t,"y3")
    local real a = GetHandleReal(t,"a")
    local real b = 1-a //old: GetHandleReal(t,"b")
    local unit dum=GetHandleUnit(t, "dum") //for god's sake, do you know how heavy is such a handle var call?
                                           //you were calling it thousands of times
    
    
    call SetUnitPosition(dum, BezierCurveValue(a,b,x1,x3,x2), BezierCurveValue(a,b,y1,y3,y2))
    
    call SetUnitAnimation(dum, "walk")
    
    //Using a constant is for sure faster than ConvertUnitState:
    if IsUnitInRangeXY(dum,x2,y2, 100) or GetUnitState(dum,UNIT_STATE_LIFE) <= 0 then // end of dummy is near end point
        call KillUnit(dum)
        call RemoveUnit(dum)
        call FlushHandleLocals(t)
        call PauseTimer(t)
        call DestroyTimer(t)
    endif
    call SetHandleReal(t,"a",a + .01)
    //Note that an increment of 0.01 means that it will need 100 timer cycles to complete the move.
    // make a go from 0 - 1 and b from 1-0 like Vex said
    //no need : call SetHandleReal(t,"b",b - .01)

    set t = null
    set dum=null
endfunction

function ShadowBreeze_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()        
    local timer t = CreateTimer()   
    local real x1 = GetUnitX(u)  // reals for point A
    local real y1 = GetUnitY(u)
    local location l = GetSpellTargetLoc()     
    local real x2 = GetLocationX(l)  // reals for Point C
    local real y2 = GetLocationY(l)     
    local unit dum = CreateUnit(p, 'n000', x1, y1, a) //what 'a'? , I don't see any declaration for that
       

    local real dist = SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))/2
    local real dist2 = SquareRoot((dist*dist)+(200*200))   
    // used Pythagoreaum Thereom to get location of point B
    
   
    local real x3 = x1 + dist2 * Cos(a * bj_DEGTORAD)  // Reals for point B
    local real y3 = y1 + dist2 * Sin(a * bj_DEGTORAD)
    // I don't get the logic of these calculations, and I don't know how do you calculate a
    // most likely the calculation of a
    
    call SetHandleReal(t,"x3",x3) 
    call SetHandleReal(t,"y3",y3)
    call SetHandleReal(t,"x1",x1) 
    call SetHandleReal(t,"y1",y1)
    //call SetHandleReal(t,"a",0) // set a to 0 and b to 1 like Vex said to start with
    // No need to save a, it already starts at 0.
    
    //call SetHandleReal(t,"b",1)   No, no need to save b in game cache 
   
    call UnitApplyTimedLife(dum, 'BTLF', 2)
    call SetHandleReal(t,"x2",x2)
    call SetHandleReal(t,"y2",y2)
    call SetHandleHandle(t, "dum", dum)    
    
    call SetUnitTimeScalePercent(dum, 10000)
    call SetUnitAnimation(dum, "walk")
    call TimerStart(t, .025, true, function ShadowBreeze_Walk)
    call TriggerSleepAction(0)
    
    call MoveUnitToPolarProjection(u,SquareRoot((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))+50, a)    
    call SetUnitFacing(u,bj_RADTODEG * Atan2(GetUnitY(u)-y2,GetUnitX(u)-x2)) // this is unit targetable, so gotta move the caster to the target
    
    set t = null
    set u = null
    call RemoveLocation(l)
    set l = null
    set dum = null
endfunction
03-09-2006, 06:40 AM#13
emjlr3
ty a mil Vex, works like a charm now

and it seems funny to me, but most of what you had me change was just for asthetic purposes, and didnt seem to really change at all what it was really doing, the main prob may have been the angle a, that I fixed, ty again!

my only complaint Vex is this, at times, the arc looks perfect, and other times, it looks ok, and other times it looks like crap

I could use it 10 times in a row from the same spot to the same spot and each time it looks different, why the variability?
03-09-2006, 10:24 AM#14
Vexorian
I would blame your angle a calculation.

And the difference between calling GetHandeUnit(t,"dum") 13 times in a row and just calling it once is a huge performance difference
03-09-2006, 08:39 PM#15
emjlr3
i fixed that, and yes it was my angle i still had it screwed up, instead of using the angle between the target and caster, then adding or subtracting 45 to it to get my point C, i was just using 45 and -45, it looks amazing now, ty for your help again!

id give +rep but it seems i need to spread it still more... :(