In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: forked from: Trajectory Path formula

Normalized time=1 version.
This is a question that needs to be solved: Given a required normalized end-point velocity direction vector, determine gravity value required to meet end point velocity direction (ie. end point velocity vector). NOTE: i reversed the direction in this case. So, Given a particular angle, adjust the GRAVITY force of the projectile so it'll hit target spot.

Typical lob trajectory parabola paths in 2D. This should be converted to a 3D AGAL Vertex shader to batch draw tons of arrows or trajectory paths!
See drawPath() for guidelines.
@author Glenn Ko
/**
 * Copyright Glidias ( http://wonderfl.net/user/Glidias )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/kjCT
 */

// forked from Glidias's forked from: Trajectory Path formula
package  
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import flash.ui.Keyboard;
    
    /**
    
    Normalized time=1 version.
    Given a required normalized end-point velocity direction vectir, determine gravity value required to meet end point velocity direction (ie. end point velocity vector)
    
     * Typical lob trajectory parabola paths in 2D. This should be converted to a 3D AGAL Vertex shader to batch draw tons of arrows or trajectory paths!
     * See drawPath() for guidelines.
     * @author Glenn Ko
     */
    [SWF(frameRate="60", backgroundColor="#FFFFFF")]
    public class LobTrajectory extends Sprite 
    {
        static public const MAX_TIME:Number = 10;

 
        private var SPEED:Number = 144;
        private var DRAW_SEGMENTS:int  = 16;
        private var startPosition:Point = new Point();
        private var endPosition:Point = new Point();
        private var GRAVITY:Number = 266;
        private var totalTime:Number;
        
        private var velocity:Point = new Point();
        private var _displace:Point = new Point();
        
        private var curPosition:Point = new Point();
        private var curSprite:Sprite = new Sprite();
        
        private var initialPosition:Point = new Point();
        private var finalDirection:Point = new Point();
        private var gravOffset:Number=0;
        
        public function LobTrajectory() 
        {
            startPosition.x = 40;
            startPosition.y = stage.stageHeight -40;
            
            initialPosition.x = stage.stageWidth - 20;
            initialPosition.y = stage.stageHeight - 20;
            
            
            
            curPosition = startPosition.clone();
            
            endPosition.x  = 300;
            endPosition.y = 333;
            
            
            drawPath();
            
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            
            curSprite.graphics.beginFill(0xFF0000);
            curSprite.graphics.drawCircle(0, 0, 4);
            addChild(curSprite);
            
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDOwn);
        
        }
        
        private function onKeyDOwn(e:KeyboardEvent):void 
        {
            var keyCode:uint = e.keyCode;
            if (keyCode === Keyboard.NUMPAD_DIVIDE) {
                gravOffset -= 10;
                onMouseMove(null);
            }
            else if (keyCode === Keyboard.NUMPAD_ADD) {
                    
                gravOffset += 10;
                onMouseMove(null);
            }
            else if (keyCode === Keyboard.LEFT) {
                    initialPosition.x--;
                      onMouseMove(null);
            }
            else if (keyCode === Keyboard.RIGHT) {
                initialPosition.x++;
                  onMouseMove(null);
            }
            else if (keyCode === Keyboard.UP) {
                initialPosition.y--;
                  onMouseMove(null);
            }
            else if (keyCode === Keyboard.DOWN) {
                initialPosition.y++;
                  onMouseMove(null);
            }
        }
        
        private function onEnterFrame(e:Event):void 
        {
            var timeElapsed:Number =  (1 / 60);
                velocity.y += GRAVITY * timeElapsed;
                
                
            curPosition.x += velocity.x * timeElapsed;
            curPosition.y += velocity.y * timeElapsed;
        
            curSprite.x = curPosition.x;
            curSprite.y = curPosition.y;
            
            
        }
        
        
        
        private function onMouseMove(e:MouseEvent):void 
        {
        
              startPosition.x  = mouseX;
            startPosition.y = mouseY;
            
            curPosition.x = startPosition.x;
            curPosition.y = startPosition.y;
            
               endPosition.x = 40;
            endPosition.y = stage.stageHeight -40;
            
            finalDirection = initialPosition.subtract(endPosition);
            var distanceLeft:Number = finalDirection.length;  // the amount of 
            
            //finalDirection.normalize(1);
            
            var distanceTravelled:Number = endPosition.subtract(startPosition).length;
         //   finalDirection.y *= distanceLeft );
            
            // Some alebraic shifting to determine gravity...
            // FORMULA 1
            //  py = startPosition.y + .5 * GRAVITY * t * t + velocity.y * t
            // endPosition.y = startPosition.y + .5 * GRAVITY  + velocity.y 
            //  endPosition.y - velocity.y = startPosition.y + .5 * GRAVITY  
            
            // endPosition.y - velocity.y = .5*GRAVITY +  startPosition.y 
            
            //  (endPosition.y - velocity.y - startPosition.y)  = GRAVITY*.5;
            //  (endPosition.y - velocity.y - startPosition.y)*2  = GRAVITY;
                //  (endPosition.y - finalDirection.y - startPosition.y)*2  = GRAVITY;
            
                // FORMULA 2
                // var vx:Number = velocity.x;
               // var vy:Number =  velocity.y + GRAVITY * t;
                //var d:Number = 1 / Math.sqrt(vx * vx + vy * vy); // normalize  
                //vx *= d;
                //vy *= d;
                
                
            
            
                // vy has to be final position
                
        
             //  finalDirection.y = velocity.y + GRAVITY;
               
            
            //GRAVITY = finalDirection.y - velocity.y;
            //GRAVITY *=     2;
            // GRAVITY + velocity.y = finalDirection.y
            //
            
            
    //      GRAVITY = 266;  
           //velocity.y = finalDirection.y  - GRAVITY;
        //     GRAVITY = finalDirection.y - velocity.y  ;
               
              calcVelocity();
              
            drawPath();
        }
        
        
        private function drawPath():void 
        {    // TODO: Convert to AGAL 3d vertex shader to batch draw tons of arrows/trajectory paths, etc.
            
            // Constants: (besides obj->camera transform..)
            // 1) Gravity.w,  z = maximum arrow travel time for ~120 per draw call case.
            
            // 2 CONSTANT REGISTERS per arrow! 
            // Constants per arrow/trajectory path: (~60 per draw call)  ->  Arrow travel path time > MAX_TIME
            // 1) velocity x,y,z ,  w  = totalTimeOfPath or currentTimeOfArrowPath
            // 2) start Position x,y,z of arrow
            
            // -or - 
            // Sequeeze everything into 1 CONSTANT REGISTER pre arrow. With this single constant, the arrow position and
            // orientation can be determined:
            // Constants per arrow/trajectory path:   (~120 per draw call) ->  Arrow travel path time <= MAX_TIME
            // arrow velocity x,y,z and w(whole portion) offset and w(fractional portion) time
            // 1) velocity x,y,z ,  w  = totalTimeOfPath or currentTimeOfArrowPath (approximate fractional portion over maximum arrow travel time MAX_TIME)
            //  &   offset (rounded approx to whole number) (whole number portion, dotProduct  of arrow velocity over it's start position. By scaling dotProduct over velocity, you get the start position)
            
            graphics.clear();
            graphics.beginFill(0x000000, 1);
            graphics.lineStyle(0, 0, 1);
        
            var totalTimeToUse:Number =  (totalTime > MAX_TIME) ? totalTime : totalTime / MAX_TIME * MAX_TIME;
                   
            for (var i:int = 0; i <= DRAW_SEGMENTS; i++) {  // draw in between segments
            
                var t:Number = (i / DRAW_SEGMENTS) * totalTimeToUse;
               
                var px:Number;
                var py:Number;
                graphics.drawCircle(
                px= startPosition.x + velocity.x * t,
                py = startPosition.y + .5 * GRAVITY * t * t + velocity.y * t
                ,4);
                
                 // get forward vector
                var vx:Number = velocity.x;
                var vy:Number = velocity.y + GRAVITY*t;
                var d:Number = 1 / Math.sqrt(vx * vx + vy * vy); // normalize  
                vx *= d;
                vy *= d;
                graphics.moveTo(px, py);
                graphics.lineTo(px + vx * 11, py + vy * 11);
            }
            
            graphics.moveTo(initialPosition.x, initialPosition.y);
            graphics.lineTo(startPosition.x, startPosition.y);
            
        }
        
        // Launch arrow
        private function calcVelocity():void 
        {
            var velocityDirector:Point = startPosition.subtract(initialPosition);
            velocityDirector.normalize(1);
        
            
            var displace:Point = endPosition.subtract(startPosition);
            _displace.x = displace.x;
            _displace.y = displace.y;
            
            
            var scaler:Number = displace.x / velocityDirector.x;
            velocityDirector.x *= scaler;
            velocityDirector.y *= scaler;
            // adjust GRAVIY 
            GRAVITY = endPosition.y - startPosition.y - velocityDirector.y;
            GRAVITY *= 2;
            GRAVITY += gravOffset;
           
            totalTime = 1;
            
          
       
            displace.y -= GRAVITY * 0.5;
            
            velocity.x = displace.x;
            velocity.y = displace.y;
        }
        
    }

}