| 06-14-2009, 04:00 AM | #1 |
I've been, quite literally, working on this for the better part of an entire day. Trying to figure out how to make a projectile arc from point A... to point B. There are a good deal of examples that'll help me, but honestly, every one that I have found so far has left me clueless as to what they're talking about. (I'm referring to maps made by previous spell creators.) Could someone lay this out in simple English for me? Step by step, because evidently, this concept is beyond me. I want the Arc to start raising the character slowly, and then hover at the pinnacle for a bit, and then move down just as quickly as it had arose. I know there's a simple formula for this, I know it. I may have, even used it in one of my maps of old, but they don't seem to be opening. (Previous account was "Kojiro" and that was years past.) It's... <------------------distance--------------------> Divided by Current Distance Divided by Speed Isn't it? I have a variable tracking how far along the current point is, and if the current point is past the middle section, it starts descendig instead of increasing. But my attempts thus far have been glitchy and ugly at best. Thanks in advance. |
| 06-14-2009, 03:02 PM | #2 |
http://www.wc3c.net/showthread.php?t...light=parabola Don't know what you're using, but if you are a GUI user this might help, otherwise it should be fairly simple. The explanation isn't going to focus on the meaning, but simply how you can apply it. Okay, we have this: JASS:function ParabolaZ takes real h, real d, real x returns real return (4 * h / d) * (d - x) * (x / d) endfunction Of the actual math, there is a good explanation in the link, which you might want to read. To use a GUI form of this, all you need to do is create a new trigger. Then in your trigger perform the arithmetic on these numbers. So to sum this up, and feel free to ask more questions: Begin by indexing the units with all this information. Then have a few temporary reals, that you can set the indexing to and "pass" them into the new trigger or "function" you've created. The function then does the math specified with these reals, and produces and answer. You can then pass the answer back into the main loop. To pass it into, you are just going to set say: Temporary Height = Unit-Height[Index], then run the trigger. |
| 06-14-2009, 05:09 PM | #3 |
JASS:
private function ArcZAcceleration takes real speed, real arc, real d returns real
return -8*arc*speed*speed/d
endfunction
...
method projectToPoint takes real speed, real tx, real ty, real tz, real arc returns nothing
local real a = Atan2( ty - .y, tx - .x )
local real d = SquareRoot( ( tx - .x ) * ( tx - .x ) + ( ty - .y ) * ( ty - .y ) )
local real t = d / speed
set .gravity = ArcZAcceleration( speed, arc, d )
set .xVel = speed * Cos( a )
set .yVel = speed * Sin( a )
set .zVel = (-.gravity) * t / 2 + ( tz - .z ) / t
call SetUnitAnimationByIndex( .self, R2I( bj_RADTODEG * Atan2( .zVel, SquareRoot( .xVel * .xVel + .yVel * .yVel ) ) + 0.5 ) + 90 )
endmethod
That's what I use, the variable names should be self explanatory ... (max height = arc * distance) -> its the same as warcraft one for projectiles |
| 06-14-2009, 05:33 PM | #4 |
I would explain it like this: The projectile's acceleration in the z-axis should be negative, and constant. That means, when speed reaches 0, the projectile's height will decrease. Since the acceleration is constant, that will be in the middle of the arc, assuming it all happens on a flat surface. If not, the method works anyway, and it is the closest to realistic movement you can get. |
| 06-14-2009, 07:28 PM | #5 |
The motion is quite simple, really, it's that of an object in freefall. The only force operating on our object is gravitation, so the object is under constant acceleration in a downwards direction. The value of it, let's call it g, should be around a thousand WC3 distance units per second squared. We want our unit to take off at point A and land at point B while affected by this acceleration. This gives us a horizontal distance that we want to travel, let's call it d, and a vertical distance between the two points, let's call it z. With a given g, d and z we can easily calculate what the conditions at the start of the jump must be in order for the unit to land at point B. We just need to make one more assumption; in my first example, I'll assume a fixed horizontal speed vd, so, the further the target point is, the larger the d, the longer the jump will take. With that assumption, we can calculate the starting vertical velocity vz by equating the time it takes for the unit to travel distance d given the horizontal speed vd and the time the unit will remain in the air depending on the starting vz: t = d / vd t = 2 * vz / g d / vd = 2 * vz / g vz = (d / vd) * g / 2 We disregarded z in this case, time to take it into account: vz = (d / vd) * g / 2 + z / t vz = (d / vd) * g / 2 + z / (d / vd) There, we have the unit's starting speed expressed with vd and vz. We can further express vd with vx and vy. Then, all we have to do is move the unit with a fast periodic trigger with a period of dt, like this: JASS:set unit:vz = unit:vz - g * dt set unit:x = unit:x + unit:vx * dt set unit:y = unit:y + unit:vy * dt set unit:z = unit:z + unit:vz * dt call MoveLocation( tempLoc, unit:x, unit:y ) //needed to get the height of terrain set r = GetLocationZ(tempLoc) call SetUnitX( unit, unit:x ) call SetUnitY( unit, unit:y ) call SetUnitFlyHeight( unit, unit:z - r ) if unit:z < r then //unit has landed, end the jump. endif Another example would be if we want the jump to last a fixed duration t, rather than have a fixed horizontal speed. In this case, the equations for starting velocity are even somewhat simplified: t = d / vd t = 2 * vz / g vd = d / t vz = t * g / 2 Again, we disregarded z, here's the full equation for vz: vz = t * g / 2 + z / t There it is, the starting vd and vz required for a unit to jump from point A to point B in a fixed time. Once you calculate this, you can then use the same code that was written in the previous example to move the unit. Here's an alternative code that is somewhat more efficient, instead of moving the unit based on it's previous position it moves it based on the starting position and elapsed time: JASS:set unit:elapsedt = unit:elapsedt + dt set x = unit:startx + unit:vx * unit:elapsedt set y = unit:startx + unit:vx * unit:elapsedt call MoveLocation( tempLoc, x, y ) //needed to get the height of terrain set r = GetLocationZ(tempLoc) call SetUnitX( unit, x ) call SetUnitY( unit, y ) call SetUnitFlyHeight( unit, unit:startz + unit:vz * unit:elapsedt - g * unit:elapsedt * unit:elapsedt - r ) if elapsedt > duration then //unit has landed, end the jump. endif |
