# [JASS]A formula for the Z axle?

Status
Not open for further replies.

Level 6
We all know the formula for moving a unit around in a circle on the X&Y plane:

X + dist * cos(angle+movementspeed * pi/180)*
Y + dist * sin(angle+movementspeed * pi/180)*

* also, reset when the angle hits 359 so you keep it in the same angle all teh time

now... the Z plane, a unit's flying height that is, should have a similar formula shouldn't it? I mean, the first formula can be used in some sort of spherical example I guess, can anyone give me a precise... accurate... splendid... awesomeness formula for moving a unit in the Z plane like a circle.

(Mind you, the easy part is to make the unit go back and forth in the Y plane, I've already done it, I can also make a square-ish form using distance, movement speed etc, all from the great book o' physics)

Me likey maths, teach me

#### spiwn

Level 12
There is a formula for this.
Search for it(jump parabola/jump spell/jump formula).

Level 6
The only one I found was in vJass, and I don't know that much vJass, would you mind searching and linking/copy+paste it for me and I will spam +rep for you

#### PurplePoot

Level 40
Well, 2d is Polar Coordinates,

x = r*cos(t)
y = r*sin(t)

--

r = Sqrt(x^2+y^2)
t = arctan(y/x)

Now, for 3d (Spherical Coordinates), which is two angles and a distance, we have

x = r*cos(t)*sin(p)
y = r*sin(t)*sin(p)
z = r*cos(p)

--

r = Sqrt(x^2+y^2+z^2)
t = arctan(y/x)
p = arccos(z/r)

Level 6
Ok... could you elaborate a little? examples usually help

#### PurplePoot

Level 40
[jass=Create a sphere of units centred around 0,0,700, with an interval of pi/16, and the sphere having 500 radius, and discounting terrain height]local real r = 500
local real t
local real p = 0
loop
exitwhen p >= 2*bj_PI
set t = 0
loop
exitwhen t >= 2*bj_PI
call SetUnitFlyHeight(CreateUnit(Player(0),'h000',r*Cos(t)*Sin(p),r*Sin(t)*Sin(p),0),700+r*Cos(p),0)
set t = t + bj_PI/16
endloop
set p = p + bj_PI/16
endloop[/code]

Basically, as you said with Polar coordinates, you have:

Where radius is the circle's radius (distance), and theta is the angle.

With Spherical Coordinates, you have:

Where radius and theta are the same as before, and phi is your second angle.

#### spiwn

Level 12
Hm
I think that formula is incorrect.
Should be:
Heck, I am not 100% sure(again it's late )

Last edited:

#### PurplePoot

Level 40
I think some of them change depending on where you measure phi (incline or decline), but not like that...

#### spiwn

Level 12
Oh, bugger.
Yeah phi is not fixed. I got confused with another thing where you would have a tilted parabola - I thought phi was the angle of the tilt.
So you agree with my suggestion about sin/cos?

#### PurplePoot

Level 40
No, I've never seen that use before, to my recollection.

Wikipedia said:
x = r sin θ cos ϕ
y = r sin θ sin ϕ
z = cos θ

Wolfram said:
x = r cos θ sin ϕ
y = r sin θ sin ϕ
z = cos ϕ

They agree, only θ and ϕ are reversed.

#### spiwn

Level 12

First thought: wtf.
A period of thinking.
Urika
Both ways are absolutely correct.
But it is the order at which you are going to place the the objects.
If phi starts from 0:
Your's/wiki's way will start at the top and will go down drawing a circle. My will start at the middle and go up, drawing a circle.
With the first way phi would indicate the angle with the vertical plane. With my way - the angle with the horizontal plane.
It is a matter of personal appeal as setting phi to the right value in one of the methods would make both ways the same.
To me it is more natural that the height should be sin*radius.
Here is the simple test:

JASS:
``````local real r = 600
local real t = bj_PI/64
local real p = 0
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 3000.00, 0 )
loop
exitwhen p >= 2*bj_PI
call PolledWait(0.2)
set p = p + bj_PI/32//to miss one branch
set t = t + bj_PI/32//to miss one branch
endloop``````

#### PurplePoot

Level 40
spiwn, if ϕ is the horizontal angle then it should be wiki's way, which is way different from yours.

Therefore, you're doing something else (and I can't work out the math right now, too tired), or you're confusing yourself.

#### spiwn

Level 12
No i am not
And also note that "exitwhen p >= 2*bj_PI" is wrong.
Should be exitwhen p >= bj_PI.
Here are the two tests for spheres
JASS:
``````local real r = 600
//local real t = (-1*bj_PI/2) + bj_PI/64
//local real p = -1*bj_PI/2
//local real end = bj_PI/2
local real t = bj_PI/64
local real p = 0
local real end = bj_PI
local real g
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 3000.00, 0 )
loop
exitwhen p >= end
set g=0
loop
exitwhen g>=2*bj_PI
set g=g+bj_PI/32
endloop
call TriggerSleepAction(-1)
set p = p + bj_PI/32
set t = t + bj_PI/32
endloop``````
I doubt I need to say something about the "//"
About the angle, just run the two tests

Last edited:

#### PurplePoot

Level 40
True, as I said, I'm tired at the moment.

(Technically, it's 2*bj_PI, but that repeats everything twice).

Also, about your formula, where are the angles measured from? That's the most important question.

Level 6
Wow, you've given lots of information, me likey spheres but I also want to know how and why they turn out the shapes they do. I'm not THAT good at math yet, explain in layman terms... this is my stupid code for the moment, trying to use your info to create it. As I mentioned earlier (I think) I'm trying to move a unit using the y and z plane only.

Here's my stupid code:

JASS:
``````function height takes nothing returns nothing
local gamecache gc = udg_AbilityCache
local string s = I2S(H2I(GetExpiredTimer()))
local real r = GetStoredReal(gc, s, "r")
local real x = GetStoredReal(gc, s, "x")
local real y = GetStoredReal(gc, s, "y")
local real h = GetStoredReal(gc, s, "h")
local real newh = h + 600*Cos(bj_PI/16)
call SetUnitFlyHeight( gg_unit_hgry_0023, newh, 10000)
call SetUnitX( gg_unit_hgry_0023, somex....)
call StoreReal( gc,s, "h", newh)
endfunction
function Trig_lul_Actions takes nothing returns nothing
local gamecache gc = udg_AbilityCache
local timer t = CreateTimer()
local string s = I2S(H2I(t))
local real r = 0
local real x = GetUnitX(gg_unit_hgry_0023)
local real y = GetUnitY(gg_unit_hgry_0023)
local real h = GetUnitFlyHeight( gg_unit_hgry_0023 )
call StoreReal(gc, s, "r", r)
call StoreReal(gc, s, "x", x)
call StoreReal(gc, s, "y", y)
call StoreReal(gc, s, "h", h)
call TimerStart( t, 0.5, true, function height)
endfunction

//===========================================================================
function InitTrig_lul takes nothing returns nothing
set gg_trg_lul = CreateTrigger(  )
call TriggerRegisterPlayerChatEvent( gg_trg_lul, Player(0), "go", true)
call TriggerAddAction( gg_trg_lul, function Trig_lul_Actions )
endfunction``````

I have absolutely no clue of what to do...

EDIT: If you could create a map for me doing this and giving comments or, drawing some sort of picture on how these formulas work I'd be forever grateful

Level 21
Bah nobody uses Bezier anymore, when they are a lot better than other formulas.

This can be simplified to a basic interpolation formula:

JASS:
``````function LinearInterp takes real a, real b, real t returns real
return a + (b-a)*t
endfunction
function BezierInterp takes real a, real b, real c, real t returns real
return a + 2*(b-a)*t + (c -2*b + a)*t*t
endfunction``````

In this 3 points bezier curve a, b, c represent points respectively and t represents the step, 0 >= t <= 1.

now lets say we are going to make a perfect parabol.
in a jump, we would try to make a perfect parabol without much problems. The first condition we set for the X & Y axis is that, a is the start point, b is the mid point between c and a; and c is the end point. Thus X & Y axis will be interpolated linearly, and we will eliminate b, since it's the midpoint.

for Z axi (heigth) we'll use the bezier interpolation, if we take into account that heigth is an absolute value, then a = c, no matter in which terrain type the unit starts and ends, in ground of heigth is 0.0. Thus:

JASS:
``````function ParabolicInterp takes real a, real b, real t returns real
return a + 2*(b-a)*t + 2*(a-b)*t*t //we multiply last by -1 and we change inside symbols
endfunction
//thus it simplifies to
function ParabolicInterp takes real a, real b, real t returns real
return a + 2*(b-a)*(1.0-t)*t
endfunction``````

but if we are interpolating over and over then 2*(b-a) would turn into a constant value so it ends up being.
JASS:
``````function ParabolicInterp takes real a, real m, real t returns real
return a + m*(1.0-t)*t  //where m is 2*(b-a)
endfunction``````
I posted this on the vJASS Jump Thread. It saves a lot of work, rather than using cosine and sine all the time. Btw use the function on In-line.

since you are mainly interested on the effect I'll explain how to use it.

We are going to have an start point, an end point and a heigth. For interpolating X&Y axis we use this function:

JASS:
``````function LinearInterp takes real a, real b, real t returns real
return a + (b-a)*t
endfunction
//a = start point and b = endpoint``````

use it inline, it means that you are going to paste the function's return in your main function and replace the parameters.

You may be wondering what t does, imagine it like a frame step. the first point is made when t = 0, when t = 1, it returns the end point and when t = 0.5 it returns the mid point.

Use it for each axis individually.

Example:
JASS:
``````globals
unit Ur
real x
real y
real my
real mx
real t
real steps
endglobals

function Move takes nothing returns nothing
call SetUnitX(Ur, x + mx*t)
call SetUnitY(Ur, y + my*t)
if t >= 1.0 then
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endif
set t = t + steps
endfunction

function TestInterp takes unit u, real x1, real x2, real y1, real y2, real s, real time returns nothing
local timer R = CreateTimer()
set t = 0.0
set Ur = u
set x = x1
set y = y1
set mx = x2-x1
set my = y2-y1
set steps = 1.0/s
set time = time/s
call TimerStart(R,time,true,function Move)
endfunction

function Main takes nothing returns nothing
local unit u = CreateUnit(Player(0),'h000',0.0,0.0, 270.0)
call TestInterp(u,0.0,500.0,0.0,-200.0, 10.0, 1.0)
endfunction``````

Now lets modify it so, he jumps, using the parabolic function, for the z axis.

JASS:
``````globals
unit Ur
real x
real y
real z
real my
real mx
real mz
real t
real steps
endglobals

function Move takes nothing returns nothing
call SetUnitX(Ur, x + mx*t)
call SetUnitY(Ur, y + my*t)
call SetUnitFlyHeight( Ur, z + mz*(1.0-t)*t, 10000)
if t >= 1.0 then
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
endif
set t = t + steps
endfunction

function TestInterp takes unit u, real x1, real x2, real z1, real y1, real y2, real h, real s, real time returns nothing
local timer R = CreateTimer()
set t = 0.0
set Ur = u
set x = x1
set y = y1
set z = z1
set mx = x2-x1
set my = y2-y1
set mz = 2*(h-z1)
set steps = 1.0/s
set time = time/s
call TimerStart(R,time,true,function Move)
endfunction

function Main takes nothing returns nothing
local unit u = CreateUnit(Player(0),'h000',0.0,0.0, 270.0)
call TestInterp(u,0.0,500.0,0.0,0.0,-200.0, 500.0, 10.0, 1.0) //multiply the true heigths by 2
endfunction``````

Last edited:

#### Ciebron

Level 11
or u just use this

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)+75
endfunction``````

Status
Not open for further replies.

Replies
14
Views
1K
Replies
67
Views
4K
[vJASS] Spin 3D
Replies
11
Views
2K
Replies
3
Views
637
Replies
34
Views
2K