forked from: Verlet Circle / Sodaplay

by hakerlab forked from Verlet Circle / Sodaplay (diff: 1)
♥0 | Line 160 | Modified 2015-10-20 19:06:06 | MIT License
play

ActionScript3 source code

/**
 * Copyright hakerlab ( http://wonderfl.net/user/hakerlab )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ypeu
 */

// forked from k__'s Verlet Circle / Sodaplay
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.Rectangle;

    public class Main extends Sprite {
        private var points:Vector.<VerletPoint>;
        private var sticks:Vector.<VerletStick>;
        private var rect:Rectangle;
        private var acc:uint=1;
        private var len:uint=20;
        private var bDrag:Boolean;
        private var dIndex:uint;
        
        public function Main() {
            points=new Vector.<VerletPoint>;
            sticks=new Vector.<VerletStick>;
            rect=new Rectangle(0,0,stage.stageWidth,stage.stageHeight);
            
            for (var i:uint = 0; i < len; i ++) {
                var theta:Number = Math.PI * 2 / len * i;
                points.push(new VerletPoint(Math.cos(theta) * 100 + stage.stageWidth/2, Math.sin(theta) * 100 + stage.stageHeight / 2));
                
                points[i].y += 4;
            }
            
            for (i = 0; i < len; i ++) {
                sticks.push(new VerletStick(points[i], points[(i + 1) % len]));
                sticks.push(new VerletStick(points[i], points[(i + 8) % len]));
            }
            
            addEventListener(Event.ENTER_FRAME, h_enterFrame);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, h_mouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, h_mouseUp);
        }

        private function h_enterFrame(evt:Event):void {
            var i:uint,j:uint;
            for (i = 0; i < points.length; i ++) {
                points[i].update();
            }
            for (i = 0; i < points.length; i ++) {
                for (j = 0; j < acc; j ++) {
                    points[i].constrain(rect);
                }
            }
            for (i = 0; i < sticks.length; i ++) {
                for (j = 0; j < acc; j ++) {
                    sticks[i].update();
                }
            }

            if (bDrag) {
                points[dIndex].x = mouseX;
                points[dIndex].y = mouseY;
            }

            graphics.clear();
            
            for (i = 0; i < points.length; i ++) {
                if (!bDrag) {
                    var dx:Number = points[i].x - mouseX;
                    var dy:Number = points[i].y - mouseY;
                    if (dx * dx + dy * dy < 200) {
                        points[i].highlight(graphics);
                    }
                }
                points[i].render(graphics);
            }

            for (i = 0; i < sticks.length; i ++) {
                sticks[i].render(graphics);
            }
        }
        
        private function h_mouseDown(evt:MouseEvent):void {
            for (var i:uint = 0; i < points.length; i ++) {
                var dx:Number = points[i].x - mouseX;
                var dy:Number = points[i].y - mouseY;
                if (dx * dx + dy * dy < 200) {
                    dIndex = i;
                    bDrag = true;
                }
            }
        }
        
        private function h_mouseUp(evt:MouseEvent):void {
            bDrag = false;
        }

    }
}

import flash.display.Graphics;
import flash.geom.Rectangle;

class VerletPoint {
    public var x:Number;
    public var y:Number;
    private var ox:Number;
    private var oy:Number;

    public function VerletPoint(x:Number, y:Number) {
        setPos(x, y);
    }
    public function update():void {
        var tx:Number=x;
        var ty:Number=y;
        x+=vx;
        y+=vy;
        ox=tx;
        oy=ty;
    }
    public function setPos(x:Number, y:Number):void {
        this.x=ox=x;
        this.y=oy=y;
    }
    public function constrain(rect:Rectangle):void {
        x=Math.max(rect.left,Math.min(rect.right,x));
        y=Math.max(rect.top,Math.min(rect.bottom,y));
    }
    public function set vx(n:Number):void {
        ox=x-n;
    }
    public function set vy(n:Number):void {
        oy=y-n;
    }
    public function get vx():Number {
        return x - ox;
    }
    public function get vy():Number {
        return y - oy;
    }
    public function render(g:Graphics):void {
        g.beginFill(0xFF6600, 0.5);
        g.drawCircle(x, y, 3);
        g.endFill();
    }
    public function highlight(g:Graphics):void {
        g.beginFill(0xFF66FF, 0.5);
        g.drawCircle(x, y, 5);
        g.endFill();
    }
}

class VerletStick extends Array {
    private var pa:VerletPoint;
    private var pb:VerletPoint;
    private var len:Number;

    public function VerletStick(pa:VerletPoint, pb:VerletPoint, len:Number = -1) {
        this.pa=pa;
        this.pb=pb;
        if (len==-1) {
            var dx:Number=pa.x-pb.x;
            var dy:Number=pa.y-pb.y;
            this.len=Math.sqrt(dx*dx+dy*dy);
        } else {
            this.len=len;
        }
    }

    public function update():void {
        var dx:Number=pb.x-pa.x;
        var dy:Number=pb.y-pa.y;
        var d:Number=Math.sqrt(dx*dx+dy*dy);
        var diff:Number=len-d;
        var offsetX:Number = (diff * dx / d) / 2;
        var offsetY:Number = (diff * dy / d) / 2;
        pa.x-=offsetX;
        pa.y-=offsetY;
        pb.x+=offsetX;
        pb.y+=offsetY;

    }
    public function render(g:Graphics):void {
        g.lineStyle(0,0xFF6600,0.5);
        g.moveTo(pa.x, pa.y);
        g.lineTo(pb.x, pb.y);
    }
}