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

バネを円状につないだ

ActionScript3.0アニメーション読んでます。
バネの勉強しなおしってことで。

1つのボールが両隣&向いのボールとバネで繋がれてます。
Get Adobe Flash player
by sakef 24 Mar 2011
/**
 * Copyright sakef ( http://wonderfl.net/user/sakef )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/q3Kp
 */

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.DropShadowFilter;
    
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="40")]
    public class Main extends Sprite
    {
        private static const RADIUS:Number = 80;
        private static const RADIUS_BALL:Number = 13; 
        private static const BALL_NUM:int = 8;
        
        private var len_side:Number;
        private var len_opp:Number;
        private var balls:Vector.<Ball>;
        private var drag_ball:int;
        private var prev_mouseX:Number;
        private var prev_mouseY:Number;
        
        public function Main()
        {
            // 初期化
            balls = new Vector.<Ball>(BALL_NUM, true);
            for(var i:int=0, theta:Number=0 ; i<BALL_NUM ; i++, theta += 360/BALL_NUM)
            {
                balls[i] = addChild(new Ball(Math.cos(theta*Math.PI/180)*80 + 100, Math.sin(theta*Math.PI/180)*80 + 100, i, RADIUS_BALL)) as Ball;
                balls[i].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                balls[i].buttonMode = true;
            }
            
            // 隣接してるボールとの距離
            len_side = Math.sqrt((balls[0].x - balls[1].x)*(balls[0].x - balls[1].x) + (balls[0].y - balls[1].y)*(balls[0].y - balls[1].y));
            
            // 向かいのボールとの距離
            len_opp = RADIUS * 2;
            
            prev_mouseX = mouseX;
            prev_mouseY = mouseY;
            drag_ball = -1;
            filters = [new DropShadowFilter(4,45,0x777777)];
            addEventListener(Event.ENTER_FRAME, onFrame);
        }
        
        // マウスアップ時に実行する関数
        private function onMouseUp(e:MouseEvent):void
        {
            balls[drag_ball].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            stage.removeEventListener(MouseEvent.MOUSE_UP , onMouseUp);
            drag_ball = -1;
        }
        
        // マウスダウン時に実行する関数
        private function onMouseDown(e:MouseEvent):void
        {
            var ball:Ball = (e.target as Ball);
            drag_ball = ball.id;
            ball.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP , onMouseUp);
        }
        
        // 計算
        private function onFrame(e:Event):void
        {
            var i:int, j:int;
            graphics.clear();
            graphics.lineStyle(6,0xFF0000);
            graphics.beginFill(0xFFFF00,1);
            
            // ドラッグ中のBallを計算
            if(drag_ball != -1)
            {
                var d:Ball = balls[drag_ball];
                d.dx = mouseX - prev_mouseX;
                d.dy = mouseY - prev_mouseY;
                d.x = mouseX;
                d.y = mouseY;
            }
            prev_mouseX = mouseX;
            prev_mouseY = mouseY;
            
            // 向い同士のボールを使って座標計算
            var half:int = BALL_NUM * 0.5;
            for(i=0 ; i<half ; i++)
            {
                j = i+half;
                if(i != drag_ball) moveBallSpring(balls[i], balls[j], len_opp);
                if(j != drag_ball) moveBallSpring(balls[j], balls[i], len_opp);
            } 
            
            //隣同士のボールを使って座標計算
            var ball:Ball = balls[0];
            var last:Ball = balls[BALL_NUM-1];
            var startCx:Number=(ball.x + last.x) * 0.5;
            var startCy:Number=(ball.y + last.y) * 0.5;
            graphics.moveTo(startCx, startCy);
            for(i=0 ; i<BALL_NUM ; i++)
            {
                j = (i+1)%BALL_NUM;
                ball = balls[i];
                var next:Ball=balls[j];
                var cx:Number=(ball.x + next.x) * 0.5;
                var cy:Number=(ball.y + next.y) * 0.5;
                if(i < BALL_NUM-1) graphics.curveTo(ball.x, ball.y, cx, cy);
                if(i != drag_ball) moveBallSpring(ball, next, len_side);
                if(j != drag_ball) moveBallSpring(next, ball, len_side);
            } 
            graphics.curveTo(last.x, last.y, startCx, startCy);
            graphics.endFill();
            
            // 壁とのあたり判定
            for(i=0;i<BALL_NUM;i++)
            {
                ball = balls[i];
                if(ball.id != drag_ball)
                {
                    if(ball.x < RADIUS_BALL)
                    {
                        ball.x = RADIUS_BALL;
                        ball.dx *= -1;
                    }
                    if(ball.y < RADIUS_BALL)
                    {
                        ball.y = RADIUS_BALL;
                        ball.dy *= -1;
                    }
                    if(ball.x > stage.stageWidth-RADIUS_BALL)
                    {
                        ball.x = stage.stageWidth-RADIUS_BALL;
                        ball.dx *= -1;
                    }
                    if(ball.y > stage.stageHeight-RADIUS_BALL)
                    {
                        ball.y = stage.stageHeight-RADIUS_BALL;
                        ball.dy *= -1;
                    }
                }
            }
        }
        
        // ボールの位置を計算する (バネの動き)
        private function moveBallSpring(ball:Ball, target:Ball, length:Number):void
        {
            var theta:Number = Math.atan2(target.y - ball.y, target.x - ball.x);
            ball.dx += ((target.x - Math.cos(theta) * length) - ball.x) * 0.1;
            ball.dy += ((target.y - Math.sin(theta) * length) - ball.y) * 0.1;
            ball.x += ball.dx;
            ball.y += ball.dy;
            ball.dx *= 0.95;
            ball.dy *= 0.95;
        }
    }
}

// ボールクラス
import flash.display.Sprite;
class Ball extends Sprite
{
    public var dx:Number;
    public var dy:Number;
    public var id:int;
    
    public function Ball(x:Number, y:Number, id:int, radius:Number)
    {
        this.x = x;
        this.y = y;
        this.id = id;
        dx = dy = 0;
        
        graphics.beginFill(0xffffff,1);
        graphics.lineStyle(radius*0.5,0x00ff00);
        graphics.drawCircle(0,0, radius);
        graphics.endFill();
    }
}