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

Simple Harmonic Motion (string-mass system)

its nor 100%, but there's some motion already.
code not clean. idk if its really right.
/**
 * Copyright Thy ( http://wonderfl.net/user/Thy )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/o5vy
 */

// its nor 100%, but there's some motion already.
// code not clean. idk if its really right.
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    /**
     * ...
     * @author Thi
     * 
     * fórumlas do MHS (Movimento Harmônico Simples) e sistema massa-mola
     * SHM formulas (Simple Harmonic Motion) and spring-mass system
     *        数式は、(簡易高調波モーション)と 春の質量系 .. i guess ^^' (google transl)
     * 
     * x = c (°) * 'x max'    | x = x position
     * 'x max' = r            | r = amplitude
     * (°) = °o + w * t       | (°) = angle
     *                        | °o = initial angle
     *                        | t = time
     *                        | c = cos
     * v = -s (°) * 'v max'   | v = x velocity
     * 'v max' = w * r        | s = sen
     * w = 2 * pi / T         | w = angular velocity
     *                        
     * a = -xw²               | a = x acceleration
     * T = 2 * pi * sqtr(m/k) | T = period
     *                        | m = mass
     *                        | k = spring constant
     *                        | pi = 3.14...
     *                        | sqtr = square root
     * Fe = -kx               | Fe = elastic Force
     * Ee = kx²/2             | Ee = elastic Energy
     * Ec = mv²/2             | Ec = cinetic Energy
     */
    public class Main extends Sprite 
    {
        private var 
        X:Number = 1, R:Number, ANG:Number, ANGO:Number = 0, t:Number = 0, 
        V:Number, W:Number, 
        ACC:Number, T:Number, M:Number = 1, K:Number = 1,
        FE:Number, EE:Number, EC:Number;
        
        // 1 meter is equal to 10 pixels
        private var scale:Number = 100 
        // position x where the string have Fe = 0, and the cy
        private var cx:Number = 465/2, cy:Number = 465/2
        
        
        // mola (string), ball (body)
        private var mola:Shape, ball:Shape
        private var amplitude_circle:Shape
        private var ang_ball:Shape
        //
        private var seta_X:Shape
        private var seta_V:Shape
        private var seta_ACC:Shape
        
        //
        private var drag:Boolean
        
        // background
        private var 
        back_data:BitmapData = new BitmapData(465, 465, false, 0xFFFFFF),
        back_bitmap:Bitmap = new Bitmap(back_data, "auto", true)
        
        // result variables (9 vars)
        private var 
        r_ANG:TextField, 
        r_X:TextField, r_V:TextField, r_ACC:TextField,
        r_T:TextField, r_W:TextField,
        r_FE:TextField,
        r_EE:TextField,    r_EC:TextField
        
        // input variables (5 vars)
        private var 
        i_ANGO:TextField, i_R:TextField,
        i_M:TextField, i_K:TextField,
        i_SCALE:TextField
        
        
        
        // temp
        private var g:Graphics
        private var i:int, j:int, k:int, l:int
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // 
            stage.frameRate = 40            
            
            // shape init
            shape_init()
            // positions
            ball.x = ang_ball.x = cx + X * scale
            amplitude_circle.x = cx
            mola.y = ball.y = amplitude_circle.y = ang_ball.y = cy
            //
            R = X
            T = Math.sqrt(K / M)
            W = 2 * Math.PI / T
            
            // text init
            text_init()
            
            // childs
            addChild(back_bitmap)
            //
            addChild(i_ANGO)
            addChild(i_K)
            addChild(i_M)
            addChild(i_R)
            addChild(i_SCALE)
            addChild(r_ANG) 
            addChild(r_X)
            addChild(r_V)
            addChild(r_ACC)
            addChild(r_T)
            addChild(r_W)
            addChild(r_FE)
            addChild(r_EE)
            addChild(r_EC)
            //
            addChild(mola) // w:115, h:10
            addChild(amplitude_circle)
            addChild(ang_ball)
            addChild(ball) // w:11, h:11
            //
            addChild(seta_X)
            addChild(seta_V)
            addChild(seta_ACC)
            //
            mola.scaleX = (cx + X * scale) / cx // adjust scale (with ball position)
            
            
            // listeners
            stage.addEventListener(MouseEvent.MOUSE_DOWN, start_drag)
            stage.addEventListener(Event.ENTER_FRAME, enter_frame)
            stage.addEventListener(KeyboardEvent.KEY_DOWN, key_down)
            
        }
        
        private function shape_init():void
        {
            // mola (string)
            var bend:int = 5
            var step:Number = (cx - 15) / bend*.5
            mola = new Shape()
            g = mola.graphics
            g.lineStyle(0)
            g.lineTo(j = 5, k = 0)
            i = -1
            while (++i < bend)
            {
                g.lineTo(j += step, k - 5)
                g.lineTo(j += step, k + 5)
            }
            g.lineTo(j += 5, k)
            g.lineTo(j += 5, k)
            
            // ball (body)
            ball = new Shape()
            g = ball.graphics
            g.lineStyle(4, 0)
            g.beginFill(0)
            g.drawCircle(0, 0, 10)
            g.endFill()
            
            // amplitude circle 
            amplitude_circle = new Shape()
            g = amplitude_circle.graphics
            g.lineStyle(4, 0)
            g.drawCircle(0, 0, X*scale)
            
            // angle ball
            ang_ball = new Shape()
            g = ang_ball.graphics
            g.lineStyle(4, 0)
            g.beginFill(0xFFFFFF)
            g.drawCircle(0, 0, 5)
            g.endFill()
            
            // setas (arrows)
            seta_X = new Shape()
            g = seta_X.graphics
            g.lineStyle(4, 0xFF0000)
            g.lineTo(100, 0)
            seta_X.x = cx
            seta_X.y = 400 - 30
            //
            seta_V = new Shape()
            g = seta_V.graphics
            g.lineStyle(4, 0x00FF00)
            g.lineTo(100, 0)
            seta_V.x = cx
            seta_V.y = 400 - 20
            //
            seta_ACC = new Shape()
            g = seta_ACC.graphics
            g.lineStyle(4, 0x0000FF)
            g.lineTo(100, 0)
            seta_ACC.x = cx
            seta_ACC.y = 400 - 10
            
            
        }
        
        private function text_init():void
        {
            
            i_ANGO = set_text(i_ANGO, true, 160)
            i_K = set_text(i_K, true, 160)
            i_M = set_text(i_M, true, 160)
            i_R = set_text(i_R, true, 160)
            i_SCALE = set_text(i_SCALE, true, 140)
            i_ANGO.text = "°o ="
            i_K.text = "k ="
            i_M.text = "m ="
            i_R.text = "A ="
            i_SCALE.text = "scale ="
            i_ANGO.x = 0
            i_ANGO.y = 0
            i_K.x = 0
            i_K.y = 20
            i_M.x = 0
            i_M.y = 40
            i_R.x = 210
            i_R.y = 0
            i_SCALE.x = 210
            i_SCALE.y = 40
            //
            
            r_ANG = set_text(r_ANG, true, 110)
            r_X = set_text(r_X, true, 110)
            r_V = set_text(r_V, true, 110)
            r_ACC = set_text(r_ACC, true, 110)
            r_T = set_text(r_T, true, 110)
            r_W = set_text(r_W, true, 110)
            r_FE = set_text(r_FE, true, 110)
            r_EE = set_text(r_EE, true, 110)
            r_EC = set_text(r_EC, true, 110)
            
            
            r_ANG.text = "° =" 
            r_X.text = "x ="
            r_V.text = "v ="
            r_ACC.text = "a ="
            r_T.text = "T ="
            r_W.text = "w ="
            r_FE.text = "Fe ="
            r_EE.text = "Ee ="
            r_EC.text = "Ec ="
            
            r_ANG.x = 140 
            r_X.x = 0
            r_V.x = 0
            r_ACC.x = 0 
            r_T.x = 140
            r_W.x = 140
            r_FE.x = 280
            r_EE.x = 280
            r_EC.x = 280
            
            r_ANG.y = 400
            r_X.y = 400
            r_V.y = 420
            r_ACC.y =440
            r_T.y = 420
            r_W.y = 440
            r_FE.y = 400
            r_EE.y = 420
            r_EC.y = 440
            //
            r_X.textColor = 0xFF0000
            r_V.textColor = 0x00FF00
            r_ACC.textColor = 0x0000FF
            //
            back_data.draw(stage)
            //
            i_ANGO.text = String(ANGO)
            i_K.text = String(K)
            i_M.text = String(M)
            i_R.text = String(R)
            i_SCALE.text = String(scale)
            i_ANGO.x = 40
            i_ANGO.y = 0
            i_K.x = 40
            i_K.y = 20
            i_M.x = 40
            i_M.y = 40
            i_R.x = 250
            i_R.y = 0
            i_SCALE.x = 270
            i_SCALE.y = 40
            i_ANGO.border = i_K.border = i_M.border = i_R.border = i_SCALE.border  = true
            //
            r_ANG.x = 180 
            r_X.x = 30
            r_V.x = 30
            r_ACC.x = 30 
            r_T.x = 180
            r_W.x = 180
            r_FE.x = 320
            r_EE.x = 320
            r_EC.x = 320
            //
            r_X.textColor = 0
            r_V.textColor = 0
            r_ACC.textColor = 0            
        }
        
        
        private function set_text(te:TextField, bool:Boolean = false, wid:Number = 0):TextField
        {
            if (te == null)
            {
                trace("nul")
                te = new TextField()
            }
            var format:TextFormat = new TextFormat("Tahoma", 16)
            te.defaultTextFormat = format
            if (bool)
            {
                te.type = "input"
            }
            te.width = wid
            te.height = 20
            addChild(te)
            return te
        }
        
        
        private function start_drag(e:MouseEvent):void
        {
            stage.removeEventListener(MouseEvent.MOUSE_DOWN, start_drag)
            stage.removeEventListener(Event.ENTER_FRAME, enter_frame)
            stage.addEventListener(MouseEvent.MOUSE_UP, stop_drag)
            drag = true
            //
            if (mouseY > 60 && mouseY < 465)
            {
                mouse_move()
            }
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouse_move)
        }
        
        private function stop_drag(e:MouseEvent):void
        {
            stage.removeEventListener(MouseEvent.MOUSE_UP, stop_drag)
            stage.addEventListener(MouseEvent.MOUSE_DOWN, start_drag)
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouse_move)
            drag = false
            //
            ANG = 0
            X = R
            t = 0
            stage.addEventListener(Event.ENTER_FRAME, enter_frame)
            
        }
        
        private var key_has_down:Boolean
        private function key_down (e:KeyboardEvent):void
        {
            key_has_down = true
        }
        
        private function mouse_move(e:MouseEvent = null, bool:Boolean = false):void
        {
            if ((mouseY > 60 && mouseY < 465) || bool)
            {
                // update ball position
                if (!bool)
                {
                    R = (mouseX - cx) / scale
                }
                X = R
                // circle amplitude
                g = amplitude_circle.graphics
                g.clear()
                g.lineStyle(4, 0)
                g.drawCircle(0, 0, R * scale)
                //
                ball.x = ang_ball.x = cx + X * scale
                mola.scaleX = (cx + R * scale) / cx
                ang_ball.y = cy
                //
                i_R.text = String(R)
            }
            
            
        }
        
        private function enter_frame(e:Event):void
        {
            if (key_has_down) setup_input()
            
            T = 2*Math.PI * Math.sqrt(M / K)
            W = 2 * Math.PI / T
            t -= 1/40 // flash angles are different from physics
            ANG = -ANGO + W * t // angle, in radians already
            //
            X = Math.cos(ANG /** Math.PI / 180*/) * R // x position
            V = Math.sin (ANG /** Math.PI/180*/) * W * R // x velocity
            ACC = -X * W * W // x acceleration
            //
            FE = -K * X // elastic force
            //
            EE = K * X * X * .5 // elastic energy
            EC = M * V * V * .5 // cinetic energy
            
            // update movable shapes
            screen_update()
            
            // update texts
            var sh:Shape = new Shape()
            
            sh.rotation = (ANG) * 180 / Math.PI
            if (sh.rotation < 0)
            {
                r_ANG.text = String(Math.round(-sh.rotation)) 
            } else 
            {
                r_ANG.text = String(Math.round(360 - sh.rotation)) 
            
            }
            //r_ANG.text = String(Math.round(sh.rotation)) 
            r_X.text = String(Math.round(X * 100) / 100)
            r_V.text = String(Math.round(V * 100) / 100);
            r_ACC.text = String(Math.round(ACC * 1000)/1000)
            r_T.text = String(Math.round(T*100)/100)
            r_W.text = String(Math.round(W*100)/100)
            r_FE.text = String(Math.round(FE*100)/100)
            r_EE.text = String(Math.round(EE*100)/100)
            r_EC.text = String(Math.round(EC*100)/100)
            
            
            
        }
        
        private function setup_input():void
        {
            key_has_down  =false
            ANGO = Number(i_ANGO.text) * Math.PI / 180
            K = Number(i_K.text)
            M = Number(i_M.text)
            R = Number(i_R.text)
            scale = Number(i_SCALE.text)
            if(!Number(ANGO)) ANGO = 0
            if(!Number(K)) K = 0
            if(!Number(M)) M = 0
            if(!Number(R)) R = 0
            if (!Number(scale)) scale = 0.0001
            //
            mouse_move(null, true)
        }
        
        private function screen_update():void
        {
            ang_ball.x = cx + Math.cos(ANG /** Math.PI/180*/) * R * scale
            ang_ball.y = cy + Math.sin(ANG /** Math.PI / 180*/) * R * scale
            ball.x = cx + X * scale
            mola.scaleX = (cx + X * scale) / cx
            //
            g = seta_X.graphics
            g.clear()
            g.lineStyle(4, 0xFF0000)
            g.lineTo(X * scale, 0);
            //
            g = seta_V.graphics
            g.clear()
            g.lineStyle(4, 0x00FF00)
            g.lineTo(V/W * scale, 0)
            //
            g = seta_ACC.graphics
            g.clear()
            g.lineStyle(4, 0x0000FF)
            g.lineTo(ACC/(W*W) * scale, 0)
        }
        
        
    }
    
}