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

Box2D Good Spring

@see http://personal.boristhebrave.com/project/controller-grab-pack
@author paq89
Get Adobe Flash player
by tananuka13 24 Dec 2010
// forked from paq's [Box2D] Spring
package
{
    import Box2D.Common.b2Color;
    import Box2D.Common.Math.b2Math;
    import Box2D.Common.Math.b2Vec2;
    import Box2D.Dynamics.b2Body;
    import com.actionsnippet.qbox.objects.CircleObject;
    import com.actionsnippet.qbox.QuickBox2D;
    import com.actionsnippet.qbox.QuickObject;
    import flash.display.Graphics;
    import flash.display.MovieClip;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import net.hires.debug.Stats;
    
    /**
     * @see http://personal.boristhebrave.com/project/controller-grab-pack
     * @author paq89
     */
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")]
    public class Main extends Sprite
    {
        private var _canvas:MovieClip;
        private var _line:Shape;
        
        private var _qbox:QuickBox2D;
        
        private var _springs:Array;
        private var _circles:Array;
        
        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);
            
            // background
            var g:Graphics = graphics;
            g.beginFill(0xFFFFFF, 1);
            g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            
            // canvas
            _canvas = new MovieClip();
            addChild(_canvas);
            
            // line
            _line = new Shape();
            addChild(_line);
            
            // quickbox2d
            _qbox = new QuickBox2D(_canvas);
            _qbox.mouseDrag();
            _qbox.start();
            _qbox.createStageWalls();
            
            _circles = [];
            _springs = [];
            var prev:QuickObject;
            for (var i:int = 0; i < 5; i++)
            {
                var circle:QuickObject = _qbox.addCircle( { x:1 + Math.random() * (stage.stageWidth - 60) / 30,
                                                            y:1 + Math.random() * (stage.stageHeight - 60) / 30} );
                _circles.push(circle);
                if (prev)
                {
                    var spring:b2SpringController = new b2SpringController();
                    spring.SetBody1(prev.body);
                    spring.SetBody2(circle.body);
                    
                    spring.length = 1;
                    spring.damping = 0;
                    spring.k = 10;
                    
                    _springs.push(spring);
                }
                prev = circle;
            }
            
            addEventListener(Event.ENTER_FRAME, loop);
            
            addChild(new Stats);
        }
        
        private function loop(e:Event):void
        {
            _line.graphics.clear();
            var len:int = _springs.length;
            for (var i:int = 0; i < len; i++)
            {
                _springs[i].Step(_qbox.timeStep);
                springDraw(_springs[i]);
            }
        }
        
        private function springDraw(spring:b2SpringController):void
        {
            //Number of bends the spring makes
            var kinks:Number = 10;
            //Stub at either end that is unkinked
            var stub:Number = 0.05;
            //Kink width, as fraction of length
            var kinkWidth:Number = 0.05;
            //Set kink width s.t. kinks are at right angles at natural length
            kinkWidth = (1-2*stub)/kinks/2;
            //Color of spring
            var color:Number = 0x333333;

            var world1:b2Vec2 = spring.m_body1.GetWorldPoint(spring.m_anchor1);
            var world2:b2Vec2 = spring.m_body2.GetWorldPoint(spring.m_anchor2);

            var d:b2Vec2 = b2Math.SubtractVV(world2, world1);
            var dlen:Number = d.Normalize();
            var nX:Number = d.y * kinkWidth * spring.length * 4;
            var nY:Number = -d.x * kinkWidth * spring.length * 4;
            var p2:b2Vec2 = new b2Vec2(world1.x * (1 - stub) + world2.x * stub, world1.y * (1 - stub) + world2.y * stub);
            drawSegment(world1,p2,color);
            var prevp:b2Vec2 = p2;
            for (var i:int = 0; i <= kinks; i++)
            {
                var alt:Number = i % 2 == 0 ? -1:1;
                var pi:b2Vec2 = new b2Vec2(
                                world1.x + d.x * dlen * (stub + (1 - 2 * stub) * i / kinks) + nX * alt,
                                world1.y + d.y * dlen * (stub + (1 - 2 * stub) * i / kinks) + nY * alt
                            );
                drawSegment(prevp, pi, color);
                prevp = pi;
            }
            pi = new b2Vec2(world2.x * (1 - stub) + world1.x * stub, world2.y * (1 - stub) + world1.y * stub);
            drawSegment(prevp,pi,color);
            drawSegment(pi,world2,color);
        }
        
        private function drawSegment(p1:b2Vec2, p2:b2Vec2, color:Number):void
        {
            var g:Graphics = _line.graphics;
            g.lineStyle(1, color, 1);
            g.moveTo(p1.x * 30, p1.y * 30);
            g.lineTo(p2.x * 30, p2.y * 30);
        }
    }
}

/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

import Box2D.Dynamics.*;
import Box2D.Common.Math.*;
import Box2D.Common.*;

/// Base class for controllers. Controllers are a convience for encapsulating common
/// per-step functionality
internal class b2Controller
{
    public var m_next:b2Controller;
    public var m_prev:b2Controller;
        
    public function GetNext():b2Controller{return m_next;}
    public function GetPrev():b2Controller{return m_prev;}
    
    public virtual function Step(timestep:Number):void {}
        
    public virtual function Draw(debugDraw:b2DebugDraw):void {}
}

/// Base class for controllers. Controllers are a convience for encapsulating common
/// per-step functionality
internal class b2PairController extends b2Controller
{
    public var m_body1:b2Body;
    public var m_body2:b2Body;
    
    /// Get the anchor point on body1 in world coordinates.
    public virtual function GetAnchor1():b2Vec2{return null};
    /// Get the anchor point on body1 in world coordinates.
    public virtual function SetAnchor1(v:b2Vec2):void{};
    /// Get the anchor point on body2 in world coordinates.
    public virtual function GetAnchor2():b2Vec2{return null};
    /// Set the anchor point on body1 in world coordinates.
    public virtual function SetAnchor2(v:b2Vec2):void{};
    
    
    /// Get the first body attached to this joint.
    public function GetBody1():b2Body
    {
        return m_body1;
    }
    
    /// Get the first body attached to this joint.
    public function SetBody1(b:b2Body):void
    {
        m_body1 = b;
    }
    
    /// Get the second body attached to this joint.
    public function GetBody2():b2Body
    {
        return m_body2;
    }
    /// Get the second body attached to this joint.
    public function SetBody2(b:b2Body):void
    {
        m_body2 = b;
    }
}

/// Applies Hooke forces between a pair of bodies
internal class b2SpringController extends b2PairController
{
    /// Spring constant
    public var k:Number = 1;
    /// Damping constant
    public var damping:Number = 0;
    /// Natural length of spring
    public var length:Number = 0;
        
    public var m_anchor1:b2Vec2 = new b2Vec2();
    public var m_anchor2:b2Vec2 = new b2Vec2();
    
    /// Get the anchor point on body1 in world coordinates.
    public override function GetAnchor1():b2Vec2{
        return m_body1.GetWorldPoint(m_anchor1);
    }
    /// Get the anchor point on body1 in world coordinates.
    public override function SetAnchor1(v:b2Vec2):void{
        m_anchor1.SetV(m_body1.GetLocalPoint(v));
    }
    /// Get the anchor point on body2 in world coordinates.
    public override function GetAnchor2():b2Vec2{
        return m_body2.GetWorldPoint(m_anchor2);
    }
    /// Set the anchor point on body1 in world coordinates.
    public override function SetAnchor2(v:b2Vec2):void{
        m_anchor2.SetV(m_body2.GetLocalPoint(v));
    }
    
    public override function Step(timestep:Number):void{
        //Skip if asleep
        if(m_body1.IsSleeping() && m_body2.IsSleeping())
            return;
        
        var world1:b2Vec2 = m_body1.GetWorldPoint(m_anchor1);
        var world2:b2Vec2 = m_body2.GetWorldPoint(m_anchor2);
        
        var d:b2Vec2 = b2Math.SubtractVV(world2,world1);
        var dlen:Number = d.Normalize();
        
        //Spring force
        var springForce:b2Vec2 = d.Copy();
        springForce.Multiply( (dlen - length) * k );
        m_body1.ApplyForce(springForce, world1);
        m_body2.ApplyForce(springForce.Negative(), world2);
        
        //Damping
        if(damping!=0){
            var v1:b2Vec2 = m_body1.GetLinearVelocityFromWorldPoint(world1);
            var v2:b2Vec2 = m_body2.GetLinearVelocityFromWorldPoint(world2);
            var v:b2Vec2 = b2Math.SubtractVV(v2,v1);
            var dampingForce:b2Vec2 = d.Copy();
            dampingForce.Multiply(b2Math.b2Dot(v,d) * damping);
            m_body1.ApplyForce(dampingForce, world1);
            m_body2.ApplyForce(dampingForce.Negative(), world2);
        }
        
    }
    
    /// Draws a spring in a typical zig-zagging fashion
    public override function Draw(debugDraw:b2DebugDraw):void
    {
        //Number of bends the spring makes
        var kinks:Number = 10;
        //Stub at either end that is unkinked
        var stub:Number = 0.05;
        //Kink width, as fraction of length
        var kinkWidth:Number = 0.05;
        //Set kink width s.t. kinks are at right angles at natural length
        kinkWidth = (1-2*stub)/kinks/2;
        //Color of spring
        var color:b2Color = new b2Color(0xB8/255,0x86/255,0x0B/255);
        
        var world1:b2Vec2 = m_body1.GetWorldPoint(m_anchor1);
        var world2:b2Vec2 = m_body2.GetWorldPoint(m_anchor2);
        
        var d:b2Vec2 = b2Math.SubtractVV(world2,world1);
        var dlen:Number = d.Normalize();
        var nX:Number=d.y*kinkWidth*length;
        var nY:Number=-d.x*kinkWidth*length;
        var p2:b2Vec2 = new b2Vec2(world1.x*(1-stub)+world2.x*stub,world1.y*(1-stub)+world2.y*stub);
        debugDraw.DrawSegment(world1,p2,color);
        var prevp:b2Vec2=p2;
        for(var i:int=0;i<=kinks;i++){
            var alt:Number = i%2==0?-1:1;
            var pi:b2Vec2 = new b2Vec2(
                            world1.x+d.x*dlen*(stub+(1-2*stub)*i/kinks)+nX*alt,
                            world1.y+d.y*dlen*(stub+(1-2*stub)*i/kinks)+nY*alt
                        );
            debugDraw.DrawSegment(prevp,pi,color);
            prevp=pi;
        }
        pi = new b2Vec2(world2.x*(1-stub)+world1.x*stub,world2.y*(1-stub)+world1.y*stub);
        debugDraw.DrawSegment(prevp,pi,color);
        debugDraw.DrawSegment(pi,world2,color);
        
        
    }
}