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

Swinging board

質点+バネを陰解法で計算してゆらゆら

P.S. クリックで壁移動に変更
P.P.S: lightened the rope
Get Adobe Flash player
by saharan 20 Aug 2013
  • Related works: 3
  • Talk

    yonatan at 17 Aug 2013 05:58
    @saharan: what's the swap for?
    saharan at 17 Aug 2013 13:35
    for the stability of the simulation. if it doesn't randomize, first it solves spring[0], next solves spring[1], spring[2], ... , and last solves spring[num - 1]. this means that spring[num - 1] (closest to the board) has little error while spring[0] (closest to the wall) has much. so the strings get stretched.
    makc3d at 18 Aug 2013 04:37
    why are they curved at rest? should not they be straight?
    makc3d at 18 Aug 2013 04:57
    okay I've noticed that the rope is heavy
    bradsedito at 22 Aug 2013 20:25
    how would one move the contact points of the ropes closer together on the box? I didn't see it, or just missed it, in your code. Is it just a simple Point( x,y ) value?
    bradsedito at 22 Aug 2013 20:25
    This is beautifully smooth btw, nice

    Tags

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

package {
    import flash.text.TextFormatAlign;
    import flash.text.TextFormat;
    import flash.text.TextField;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.display.Sprite;
    [SWF(frameRate = "60", width="465", height="465")]
    public class FlashTest extends Sprite {
        private var vs:Vector.<Vtx>;
        private var ss:Vector.<Spr>;
        private var press:Boolean;
        private var fixed1:Vtx;
        private var fixed2:Vtx;
        private var box1:Vtx;
        private var box2:Vtx;
        private var wx:Number;
        private var wy:Number;
        private var tf:TextField;
        private var boardW:Number = 160;
        private var boardH:Number = 80;
        
        public function FlashTest() {
            init();
        }
        
        private function init():void {
            var numChain:int = 24;
            var chainLen:Number = 8;
            var center:Number = 465 * 0.5;
            vs = new Vector.<Vtx>(numChain * 2 + 4, true);
            ss = new Vector.<Spr>();
            var x1:Number = center - boardW * 0.5;
            var x2:Number = center + boardW * 0.5;
            var y:Number = 100;
            fixed1 = vs[0] = new Vtx(center - boardW * 0.5, y, 0);
            fixed2 = vs[numChain] = new Vtx(center + boardW * 0.5, y, 0);
            for (var i:int = 1; i < numChain; i++) {
                y += chainLen;
                vs[i] = new Vtx(x1, y, 1);
                vs[i + numChain] = new Vtx(x2, y, 1);
                ss.push(new Spr(vs[i], vs[i - 1], chainLen, false, true));
                ss.push(new Spr(vs[i + numChain], vs[i + numChain - 1], chainLen, false, true));
            }
            var i1:int = numChain * 2;
            var i2:int = numChain * 2 + 1;
            var i3:int = numChain * 2 + 2;
            var i4:int = numChain * 2 + 3;
            y += chainLen;
            box1 = vs[i1] = new Vtx(x1, y, 0.2);
            box2 = vs[i2] = new Vtx(x2, y, 0.2);
            y += boardH;
            vs[i3] = new Vtx(x1, y, 0.2);
            vs[i4] = new Vtx(x2, y, 0.2);
            ss.push(new Spr(vs[numChain - 1], vs[i1], chainLen, false, true));
            ss.push(new Spr(vs[numChain * 2 - 1], vs[i2], chainLen, false, true));
            ss.push(new Spr(vs[i1], vs[i2], boardW, true, true));
            ss.push(new Spr(vs[i3], vs[i4], boardW, true, true));
            ss.push(new Spr(vs[i1], vs[i3], boardH, true, true));
            ss.push(new Spr(vs[i2], vs[i4], boardH, true, true));
            var diag:Number = Math.sqrt(boardW * boardW + boardH * boardH);
            ss.push(new Spr(vs[i1], vs[i4], diag, true, false));
            ss.push(new Spr(vs[i2], vs[i3], diag, true, false));
            ss.fixed = true;
            
            wx = 465 * 0.5;
            wy = 100;
            
            tf = new TextField();
            var dtf:TextFormat = new TextFormat("Courier New", 30);
            dtf.leading = -14;
            dtf.align = TextFormatAlign.CENTER;
            tf.defaultTextFormat = dtf;
            tf.text = "\nA Board";
            tf.width = boardW;
            tf.selectable = false;
            addChild(tf);
            
            stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent = null):void {
                press = true;
            });
            stage.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent = null):void {
                press = false;
            });

            addEventListener(Event.ENTER_FRAME, loop);
        }
        
        private function rnd():Number {
            return Math.random() * 10 - 5;
        }
        
        private function loop(e:Event = null):void {
            graphics.clear();
            graphics.lineStyle(1, 0);
            if ((mouseX != 0 || mouseY != 0) && press) {
                wx += (mouseX - wx) * 0.4;
                wy += (mouseY - 16 - wy) * 0.4;
            }
            graphics.moveTo(0, wy);
            graphics.lineTo(465, wy);
            fixed1.vx = wx - boardW * 0.25 - fixed1.x;
            fixed1.vy = wy - fixed1.y;
            fixed2.vx = wx + boardW * 0.25 - fixed2.x;
            fixed2.vy = wy - fixed2.y;
            var numV:int = vs.length;
            for (var i:int = 0; i < numV; i++) {
                var v:Vtx = vs[i];
                v.move();
            }
            
            var nx:Number = box2.x - box1.x;
            var ny:Number = box2.y - box1.y;
            tf.x = box1.x;
            tf.y = box1.y;
            tf.rotationZ = Math.atan2(ny, nx) / Math.PI * 180;
            
            var numS:int = ss.length;
            for (var t:int = 0; t < 32; t++) {
                ss[0].move();
                for (i = 1; i < numS; i++) {
                    ss[i].move();
                    var swap:int = int(Math.random() * i);
                    var tmp:Spr = ss[i];
                    ss[i] = ss[swap];
                    ss[swap] = tmp;
                }
                for (i = 1; i < numV; i++) {
                    vs[i].wall(wy);
                }
            }
            for (i = 0; i < numV; i++) {
                vs[i].draw(graphics);
            }
            for (i = 0; i < numS; i++) {
                ss[i].draw(graphics);
            }
        }
    }
}
import flash.display.Graphics;

class Vtx {
    public var x:Number;
    public var y:Number;
    public var vx:Number;
    public var vy:Number;
    public var mass:Number;
    
    public function Vtx(x:Number, y:Number, mass:Number) {
        this.x = x;
        this.y = y;
        vx = 0;
        vy = 0;
        this.mass = mass;
    }
    
    public function move():void {
        x += vx;
        y += vy;
        if (mass != 0) {
            vy += 0.5;
        }
    }
    
    public function wall(wy:Number):void {
        if (mass != 0 && y + vy < wy) {
            vy += wy - (y + vy);
        }
    }
    
    public function draw(g:Graphics):void {
        if (mass == 0){
            g.drawCircle(x, y, 5);
        }
    }

}

class Spr {
    public var v1:Vtx;
    public var v2:Vtx;
    public var rest:Number;
    public var visible:Boolean;
    public var rigid:Boolean;
    
    public function Spr(v1:Vtx, v2:Vtx, rest:Number, rigid:Boolean, visible:Boolean) {
        this.v1 = v1;
        this.v2 = v2;
        this.rest = rest;
        this.rigid = rigid;
        this.visible = visible;
    }
    
    public function move():void {
        var dx:Number = (v2.x + v2.vx) - (v1.x + v1.vx);
        var dy:Number = (v2.y + v2.vy) - (v1.y + v1.vy);
        var dist:Number = Math.sqrt(dx * dx + dy * dy);
        if (dist == 0) return;
        var m:Number = 1 / (v1.mass + v2.mass);
        var invDist:Number = 1 / dist;
        var dvx:Number = v2.vx - v1.vx;
        var dvy:Number = v2.vy - v1.vy;
        var nx:Number = dx * invDist;
        var ny:Number = dy * invDist;
        var rvn:Number = nx * dvx + ny * dvy;
        var f:Number = m * (dist - rest + rvn * 0.8);
        if (!rigid && f < 0) f = 0;
        var fx:Number = nx * f;
        var fy:Number = ny * f;
        v1.vx += fx * v1.mass;
        v1.vy += fy * v1.mass;
        v2.vx -= fx * v2.mass;
        v2.vy -= fy * v2.mass;
    }
    
    public function draw(g:Graphics):void {
        if (!visible) return;
        g.moveTo(v1.x, v1.y);
        g.lineTo(v2.x, v2.y);
    }

}