# [Snippet] Fly

Discussion in 'Graveyard' started by Krogoth, May 5, 2014.

1. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
Libraries:
- Curves
- Fly

FAQ

Q: WTF?
A: Every object's movement in 3-dimensional space can be represented as a composition of XY (surface) and Z (height) movement.
Most custom maps XY movement is nothing more than simple linear trajectory with constant movespeed. Jump is an obvious example, where specific Z coordinates form parabola. Same maps don't have flying units realistically interact with each other and require those parabolas just as visual.
Meanwhile our sense of continuity is about 0.025 sec, we are less sensitive to rate of trajectory, so smooth trajectory and right amount of points, connected linearly, look almost same for us. Thus, speed can be updated every 0.1 sec, or 0.2 sec, or even bigger, which depends on situation (the faster is movement the less must be frequency).
Relatively small amount of points, required to satisfy our senses, makes wise to use constant set of points for geometrically similar curves.
Curves library is meant to put normalized curves, which can be easily scaled then.
Example:
Normalized = {0, 0.75, 1, 0.75, 0} (parabola)
Scaled (x400) = {0, 300, 400, 300, 0} (parabola)

Movement algorithm is made so it uses rate of curve, to minimize input data, some inner calculations and opens door for composite Z movement from different sources (by summing up all rates).
Example:
Curve = {0, 0.75, 1, 0.75, 0}
Rate of curve = {0.75, 0.25, -0.25, -0.75}

Q: How can I do my curve?
A: Very easy:

-=- Library Curves -=-

Code (vJASS):
//-=-=-=-=--=-=-=-=-=-=-=-
//-=-=-=-] Curves [-=-=-=-
//-=-=-=-=-=-=-=--=-=-=-=-

library Curves
//-=-=-=- Settings -=-=-=-
//! textmacro CURVES
constant integer CURVE_PARABOLA = 0
constant integer CURVE_PARABOLA5_RATE = 6
constant integer CURVE_PARABOLA7_RATE = 11
//! endtextmacro

//! textmacro CURVES_DATA
//CURVE_PARABOLA5
set DATA[0] = 5
set DATA[1] = 0
set DATA[2] = .75
set DATA[3] = 1
set DATA[4] = .75
set DATA[5] = 0
//CURVE_PARABOLA5_RATE
set DATA[6] = 4
set DATA[7] = .75
set DATA[8] = .25
set DATA[9] = -.25
set DATA[10] = -.75
//CURVE_PARABOLA7_RATE
set DATA[11] = 6
set DATA[12] = .6
set DATA[13] = .3
set DATA[14] = .1
set DATA[15] = -.1
set DATA[16] = -.3
set DATA[17] = -.6
//! endtextmacro
//-=-=-=--=-=-=-=-=-=-=-=-

globals
//! runtextmacro CURVES()
endglobals
struct CURVES extends array
readonly static real array DATA
private static method onInit takes nothing returns nothing
//! runtextmacro CURVES_DATA()
endmethod
endstruct
endlibrary

-=- Library Fly -=-

Code (vJASS):
//-=-=-=-=-=-=-=-=-=-=-
//-=-=-=-] Fly [-=-=-=-
//-=-=-=-=-=-=-=-=-=-=-

library Fly requires Curves, Support
globals
private integer I = 0
private unit array Unit
private timer array Timer
private integer array Curve
private real array Scale
private real array Speed
private integer array Node
private real array Height
endglobals

private function Refresh takes nothing returns nothing
set Support.workTimer = GetExpiredTimer()
set Support.workInteger = I
loop
if Support.workTimer == Timer[Support.workInteger] then
set Node[Support.workInteger] = Node[Support.workInteger] + 1
set Support.workReal = CURVES.DATA[Curve[Support.workInteger] + Node[Support.workInteger]]
set Height[Support.workInteger] = Height[Support.workInteger] + Scale[Support.workInteger] * Support.workReal
if Support.workReal < 0 then
set Support.workReal = -Speed[Support.workInteger] * Support.workReal
else
set Support.workReal =  Speed[Support.workInteger] * Support.workReal
endif
call SetUnitFlyHeight(Unit[Support.workInteger], GetUnitDefaultFlyHeight(Unit[Support.workInteger]) + Height[Support.workInteger], Support.workReal)
if Node[Support.workInteger] == CURVES.DATA[Curve[Support.workInteger]] then
if Support.workInteger == I then
set Unit[Support.workInteger] = null
else
set Unit[Support.workInteger] = Unit[I]
set Timer[Support.workInteger] = Timer[I]
set Curve[Support.workInteger] = Curve[I]
set Scale[Support.workInteger] = Scale[I]
set Speed[Support.workInteger] = Speed[I]
set Node[Support.workInteger] = Node[I]
set Height[Support.workInteger] = Height[I]
set Unit[I] = null
set Timer[I] = Support.workTimer
endif
call PauseTimer(Support.workTimer)
set I = I - 1
endif
return
endif
set Support.workInteger = Support.workInteger - 1
endloop
endfunction

function UnitFly takes unit u, integer curve, real height, real time returns nothing
set I = I + 1
set Unit[I] = u
if Timer[I] == null then
set Timer[I] = CreateTimer()
endif
call TimerStart(Timer[I], time / CURVES.DATA[curve], true, function Refresh)
set Curve[I] = curve
set Scale[I] = height
set Speed[I] = height * CURVES.DATA[curve] / time
set Node[I] = 1
set Height[I] = height * CURVES.DATA[curve + 1]
call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u) + Height[I], Speed[I] * CURVES.DATA[curve + 1])
endfunction
endlibrary

Example of usage:
Code (vJASS):
call UnitFly(GetTriggerUnit(), CURVE_PARABOLA7_RATE, 300, 2)

It makes unit fly for 2 seconds with 300 height at maximum
XY movement is done separately

Btw, if you see some memory leak, point me please

Last edited: May 6, 2014
2. ### Magtheridon96

Joined:
Dec 12, 2008
Messages:
6,006
Resources:
26
Maps:
1
Spells:
8
Tutorials:
7
JASS:
10
Resources:
26
REAL SCRIPTS HAVE CURVES.

This curves thing is just really bad man. Document it and describe what the values mean so that people would understand how to create their own trajectories.

3. ### Quilnez

Joined:
Oct 12, 2011
Messages:
3,243
Resources:
37
Icons:
2
Tools:
1
Maps:
7
Spells:
21
Tutorials:
2
JASS:
4
Resources:
37
Code (vJASS):

if Timer[I] == null then
set Timer[I] = CreateTimer()
endif
call TimerStart(Timer[I], time / CURVES.DATA[curve], true, function Refresh)
derp.. derp.. >.>

first, I really don't know how to use this, this is something new, unique, but inefficient way to generate the trajectory, I believe you can do it by using one timer and using normal dynamic indexing. Also I see you like textmacro so much, there is no point in using it too often..

btw
Code (vJASS):

private static method onInit takes nothing returns nothing
//! runtextmacro CURVES_DATA()
endmethod

you may use
`module`
to make it more elegant.

Code (vJASS):

//! textmacro CURVES
constant integer CURVE_PARABOLA = 0
constant integer CURVE_PARABOLA5_RATE = 6
constant integer CURVE_PARABOLA7_RATE = 11
//! endtextmacro

Y U NO replace textmacro & endtextmacro to globals & endglobals?

Code (vJASS):

set DATA[0] = 5
set DATA[1] = 0
set DATA[2] = .75
set DATA[3] = 1
set DATA[4] = .75
set DATA[5] = 0

and I think everything must be calculated, not defined by user. Also that means we must declare new variable like
` constant integer CURVE_PARABOLA5_RATE = 6`
to make a new trajectory? that's horrible.
and
`library Curves`
is actually doing nothing except declaring variables, however, imo this is unaccepatable.. but I like the idea where user may set the estimated time
`function Fly takes unit u, integer curve, real height, real time`

4. ### gorillabull

Joined:
Jul 17, 2011
Messages:
1,368
Resources:
2
Spells:
2
Resources:
2
why not use 3 parametric equations for the trajectory, x and y can be linear and z can be a parabola

5. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
I just that color, man

Well, those constants is nothing compared to triggers.
Declaring comfortable names with constants is usual thing
I am not sure if I can use module, because set data is put inside function
I disagree that user must do himself nothing to profit from library. This is still very user-friendly.

Some "documentation" appeard

6. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
Dalvengyr, what you mean by using 1 timer btw?
Sure, you can

Joined:
Oct 16, 2008
Messages:
9,674
Resources:
23
Models:
2
Packs:
1
Maps:
1
Spells:
16
Tutorials:
1
JASS:
2
Resources:
23
It means that instead of using 1 timer per instance, you only use 1 timer that simply loops thru all instances

and the code looks too confusing with all those textmacros when you don't even need them... and as Maggy said, please document what those values on CURVES does...

Also instead of hardcoded curves, I would prefer that you simply take an "arc" value and dynamically create the actual parabola movement using a formula...

8. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
Every timer must be supplied with its own period, otherwise it would make no sense.
The thing is, each curve is set by constant number of points, therefore period is different for different fly time. If one jump is longer than other, it will take more time and use bigger period, that's why timers can't be merged. Also, each of them has own start point.
But I can merge close timers though.
Well, I will try something.
See FAQ
These curves aren't hardcoded. Calculating actual trajectory is relatively hardcoded.
Imagine if you have zigzag trajectory. You need to write specific algorithm, which works slower, while going through coords is always same.

9. ### Quilnez

Joined:
Oct 12, 2011
Messages:
3,243
Resources:
37
Icons:
2
Tools:
1
Maps:
7
Spells:
21
Tutorials:
2
JASS:
4
Resources:
37
they can't but you can use real to replace the "duration". but still you need to use one timer..
what trigger? you dont need any trigger, if so, then still it's better to have 1 trigger than 100 constants perhaps? this is about possibility..
that is the easiest way to generate a good parabola trajectory: using a formula which I dont remember clearly. and currently this library doesnt event support horizontal parabola movement which most missile systems around here has supported that one..

you can, but with different way

this is very not-user-friendly. since they must declare and define ~7 variables first to create ONE trajectory? How if I want to launch 100 missiles and each of them has different arc? so I need to declare/define (7*100 + 100 = 800) variables first? you must be joking

seriously, that's more like a joke

10. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0

You need to do 100 different algorithms then, which, of course, means more code than 800 variables
What a shame.

All you need is to read my FAQ. You will see an explanation why the algorithm is good.

11. ### Quilnez

Joined:
Oct 12, 2011
Messages:
3,243
Resources:
37
Icons:
2
Tools:
1
Maps:
7
Spells:
21
Tutorials:
2
JASS:
4
Resources:
37
if you are using the formula that I'm talking about, you just need one or two function then you can launch more than 100 missiles at once without declaring any new variable..
nope

just a reference for you, look at how he calculate the trajectory, max height, etc. so that everything is done automatically, not manually like this
Code (vJASS):
set DATA[0] = 5
set DATA[1] = 0
set DATA[2] = .75
set DATA[3] = 1
set DATA[4] = .75
set DATA[5] = 0

EDIT:
here is the easiest formula I have found so far:
Code (Text):
((4.00 x fly_height_max) / distance_max) x (distance_max - distance_current) x (distance_current / distance_max)
but still, there is no point in making a system like this anymore, there are just too many great similliar systems which doing their job multiple times better than yours, I'm sorry but I'm just trying tbh, so that you don't need to update this uselessly, eventually imo this one will never get approved except if you can make it better than the other existing one, that means you must re-write the whole code bcs this one is obviously inefficient. I'm sorry I can't say this inefficient, but this is just too unfriendly for user, and not dynamic..

that is the big CON of this system

Last edited: May 6, 2014
12. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
This is not dialogue, you are completely retarded. My regrets.
Those parabolas are same 1 curve, not 100. If you were able to read text and understand it same time, you would not argue by such shit.

13. ### Magtheridon96

Joined:
Dec 12, 2008
Messages:
6,006
Resources:
26
Maps:
1
Spells:
8
Tutorials:
7
JASS:
10
Resources:
26
Let the user pass in an eccentricity. Generate the curves.
Don't use this Curves library crap.

It's code-smell and it has terrible disadvantages like the fact that changing one of the arrays forces you to change every other one. What if I wanted to add an extra value or change a curve completely in the middle of all the declarations? This makes everything much more prone to human error because I have to correctly change the required count and all the required indices in the array settings and the global constant declarations.

14. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
Ty
I can make functions like SetCurve and CurveSetPoint.
For example:
Code (vJASS):
call CurveSetPoint(0)
call CurveSetPoint(0)
call CurveSetPoint(0)
call CurveSetPoint(0)
call CurveSetPoint(0)
call CurveSetPoint(0) //first lesson
call CurveSetPoint(0)
call CurveSetPoint(0)
call CurveSetPoint(1)

Is it acceptable?

My algorithm isn't the best, because I use timer array. There is a lot of improvement I can bring into it.

Joined:
Oct 16, 2008
Messages:
9,674
Resources:
23
Models:
2
Packs:
1
Maps:
1
Spells:
16
Tutorials:
1
JASS:
2
Resources:
23
Why not put the FAQ into the header? Do you expect your users to remember those or to always check this thread if they forgot what those numbers are???

You cannot use a single timer because you need different periods? Ever heard of counters? You can effectively use a single timer for this that uses a .03xxxx period and a counter for each instance... Though if you look at most movement/projectile scripts out there, they don't even use counters, they simply move everything every tick...

and yeah, I agree with the Dreadlord, we don't need another one of these

16. ### Krogoth

Joined:
Apr 5, 2011
Messages:
247
Resources:
0
Resources:
0
GY, because I have no time for this

### Code Moderator

Joined:
Jun 23, 2007
Messages:
3,654
Resources:
22
Spells:
11
Tutorials:
2
JASS:
9
Resources:
22
Alright.

You can't submit two libraries in one post anyways.