バウンスボール

by freddy
テストも兼ねて過去の習作を。
ソース汚なすぎ\(^o^)/
♥0 | Line 456 | Modified 2011-02-27 01:22:28 | MIT License
play

ActionScript3 source code

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

package {
    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.ui.*;
    import flash.utils.*;
    
    //マウスイベントを処理する
    public class Bounce extends Sprite {
        private var mouseDown:Boolean = false; //マウスダウン
        private var mouseDelta:int   =0;       //マウスホイール
        private var circle:Shape;              //円
        private var ball:Ball;                 //ボール
        private var g:Number = 0.000005;       //重力加速度
        private var e:Number = 0.9;            //跳ね返り係数
        private var seg1:Segment = new Segment(0.2, 0.35, 0.5, 0.35);
        private var seg2:Segment = new Segment(0.27, 0.35, 0.34, 0.28);
        private var seg3:Segment = new Segment(0.34, 0.28, 0.41, 0.35);
        private var seg4:Segment = new Segment(0.41, 0.35, 0.48, 0.28);
        private var seg5:Segment = new Segment(0.2, 0.05, 0.25, 0.1);
        private var seg6:Segment = new Segment(0.3, 0.1, 0.25, 0.15);
        private var seg7:Segment = new Segment(0.2, 0.15, 0.25, 0.2);
        private var seg8:Segment = new Segment(0.3, 0.2, 0.25, 0.25);
        private var cir1:Circle = new Circle(0.1, 0.15, 0.07);
        private var cir2:Circle = new Circle(0.2-0.015, 0.35, 0.015);
        private var line:Shape;                //線

        //コンストラクタ
        public function Bounce() {
            //子スプライト
            var child:Sprite=new Sprite();
            child.graphics.beginFill(0xffffff);
            child.graphics.drawRect(0,0,480,480);
            child.graphics.endFill();
            child.graphics.lineStyle(0,0x000000);

            child.graphics.moveTo(seg1.a.x*1000, seg1.a.y*1000);
            child.graphics.lineTo(seg1.b.x*1000, seg1.b.y*1000);
            child.graphics.moveTo(seg2.a.x*1000, seg2.a.y*1000);
            child.graphics.lineTo(seg2.b.x*1000, seg2.b.y*1000);
            child.graphics.moveTo(seg3.a.x*1000, seg3.a.y*1000);
            child.graphics.lineTo(seg3.b.x*1000, seg3.b.y*1000);
            child.graphics.moveTo(seg4.a.x*1000, seg4.a.y*1000);
            child.graphics.lineTo(seg4.b.x*1000, seg4.b.y*1000);
            child.graphics.moveTo(seg5.a.x*1000, seg5.a.y*1000);
            child.graphics.lineTo(seg5.b.x*1000, seg5.b.y*1000);
            child.graphics.moveTo(seg6.a.x*1000, seg6.a.y*1000);
            child.graphics.lineTo(seg6.b.x*1000, seg6.b.y*1000);
            child.graphics.moveTo(seg7.a.x*1000, seg7.a.y*1000);
            child.graphics.lineTo(seg7.b.x*1000, seg7.b.y*1000);
            child.graphics.moveTo(seg8.a.x*1000, seg8.a.y*1000);
            child.graphics.lineTo(seg8.b.x*1000, seg8.b.y*1000);
            child.graphics.drawCircle(cir1.a.x*1000, cir1.a.y*1000, cir1.r*1000);    //XY座標,半径
            child.graphics.drawCircle(cir2.a.x*1000, cir2.a.y*1000, cir2.r*1000);    //XY座標,半径
            addChild(child);

            //円の追加
//            ball = new Ball(10, 240, 10, 0, 0.2, 0, 0.1);
            ball = new Ball(0.015, 0.240, 0.240, 0, 0.0007, 0.001, 0.01);
            circle=makeCircle(ball.r*1000,0xffff00);
            circle.x=ball.x*1000;
            circle.y=ball.y*1000;
            child.addChild(circle);
            
            //イベントリスナーの追加
            child.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);
            child.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler);
            child.addEventListener(MouseEvent.MOUSE_WHEEL,mouseWheelHandler);

            //タイマーの追加
            var timer:Timer=new Timer(1000/60,0);
            timer.addEventListener(TimerEvent.TIMER,onTick);
            timer.start();
        }
        
        //マウスダウンイベントの処理
        private function mouseDownHandler(evt:MouseEvent):void {
            mouseDown=true;
        }

        //マウスアップイベントの処理
        private function mouseUpHandler(evt:MouseEvent):void {
            mouseDown=false;
        }
    
        //マウスホイールイベントの処理
        private function mouseWheelHandler(evt:MouseEvent):void {
            mouseDelta=evt.delta;
        }
        
        //タイマーイベントの処理
        private function onTick(evt:TimerEvent):void {
            var i:int;
            var n:Number, m:Number;
            
            for(i=0; i<10; i++)
            {
                if(mouseDown)
                {
                    ball.vx = (mouseX/1000-ball.x)/100;
                    ball.vy = (mouseY/1000-ball.y)/100;
                }

                ball.x += ball.vx;
                ball.y += ball.vy+g/2;
                ball.vy += g;
                ball.rotation += ball.vrotation;
                
                if(ball.y >= 0.480-ball.r) // floor
                {
                    ball.y = (e+1.0)*(0.480-ball.r)-e*ball.y;
                    ball.vy = -e*ball.vy;
                    m = -2.0*(e+1.0)*ball.vx/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                    n = (2.0-e)*ball.vx/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                    ball.vrotation = m;
                    ball.vx = n;
                }
                if(ball.y < 0+ball.r) // ceil
                {
                    ball.y = (e+1.0)*(0+ball.r)-e*ball.y;
                    ball.vy = -e*ball.vy;
                    m = -2.0*(e+1.0)*(-ball.vx)/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                    n = (2.0-e)*(-ball.vx)/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                    ball.vrotation = m;
                    ball.vx = -n;
                }
                if(ball.x >= 0.480-ball.r) // right wall
                {
                    ball.x = (e+1.0)*(0.480-ball.r)-e*ball.x;
                    ball.vx = -e*ball.vx;
                    m = -2.0*(e+1.0)*(-ball.vy)/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                    n = (2.0-e)*(-ball.vy)/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                    ball.vrotation = m;
                    ball.vy = -n;

                }
                if(ball.x < 0+ball.r) // left wall
                {
                    ball.x = (e+1.0)*(0+ball.r)-e*ball.x;
                    ball.vx = -e*ball.vx;
                    m = -2.0*(e+1.0)*ball.vy/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                    n = (2.0-e)*ball.vy/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                    ball.vrotation = m;
                    ball.vy = n;
                }
                seg1.collision(ball);
                seg2.collision(ball);
                seg3.collision(ball);
                seg4.collision(ball);
                seg5.collision(ball);
                seg6.collision(ball);
                seg7.collision(ball);
                seg8.collision(ball);
                cir1.collision(ball);
                cir2.collision(ball);
            }
            
            circle.x = ball.x*1000;
            circle.y = ball.y*1000;
            circle.rotation= -ball.rotation*180/3.1415926535;
        }        
        
        //円の追加
        private function makeCircle(r:uint,color:uint):Shape {
            var circle:Shape=new Shape();
            circle.graphics.beginFill(color);     //背景色
            circle.graphics.lineStyle(0,0x000000);//線幅・線色
            circle.graphics.drawCircle(0,0,r);    //XY座標,半径
            circle.graphics.endFill();            //塗り潰し終了
//            circle.graphics.lineStyle(0,color);//線幅・線色
            circle.graphics.moveTo(0,0);     //始点のXY座標
            circle.graphics.lineTo(r,0);     //終点のXY座標
            return circle;
        }
        
        //ラインの追加
        private function makeLine(x0:int,y0:int,x1:int,y1:int,color:uint):Shape {
            var line:Shape=new Shape();
            line.graphics.lineStyle(0,color);//線幅・線色
            line.graphics.moveTo(x0,y0);     //始点のXY座標
            line.graphics.lineTo(x1,y1);     //終点のXY座標
            return line
        }
    }
}

class Ball
{
    public var r:Number;
    
    public var x:Number;
    public var y:Number;
    public var rotation:Number;
    public var vx:Number;
    public var vy:Number;
    public var vrotation:Number;
    
    public function Ball(_r:Number, _x:Number, _y:Number, _rot:Number, _vx:Number, _vy:Number, _vrot:Number)
    {
        r = _r;
        x = _x;
        y = _y;
        rotation = _rot;
        vx = _vx;
        vy = _vy;
        vrotation = _vrot;
    }
}

class Circle
{
    public var a:Vector2 = new Vector2();
    public var r:Number;
    private var e:Number = 0.9;            //跳ね返り係数 ////////////////////////////
    
    public function Circle(x:Number, y:Number, radius:Number)
    {
        a.setXY(x, y);
        r = radius;
    }
    public function collision(ball:Ball):void
    {
        var x:Vector2 = new Vector2(ball.x, ball.y);
        var n:Vector2 = new Vector2();
        var k:Number;
        var i:Number, j:Number;
        var collision:Boolean = false;
        
        
        n.setV(x);
        n.subtract(a);
        n.multiplyN(1.0-r/n.length());
        if(n.length() <= ball.r)
        {
            collision = true;
            k = ball.r-n.length();
        }
        
        if(collision)
        {
            n.normalize();
            // position
            x.setV(n);
            x.multiplyN((1+e)*k);
            ball.x += x.x;
            ball.y += x.y;
            // velocity
            var s:Matrix22 = new Matrix22(n.y, n.x, -n.x, n.y);
            var si:Matrix22 = new Matrix22(n.y, -n.x, n.x, n.y);
            x.setXY(ball.vx, ball.vy);
            x.multiplyMV(si);
            x.y = -e*x.y;
            i = -2.0*(e+1.0)*(-x.x)/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
            j = (2.0-e)*(-x.x)/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
            ball.vrotation = i;
            x.x = -j;
            x.multiplyMV(s);
            
            ball.vx = x.x;
            ball.vy = x.y;
        }
        /*
        
                ball.y = (e+1.0)*(0.480-ball.r)-e*ball.y;
                ball.vy = -e*ball.vy;
                m = -2.0*(e+1.0)*ball.vx/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                n = (2.0-e)*ball.vx/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                ball.vrotation = m;
                ball.vx = n;
        */
    }
}

class Matrix22
{
    public var m00:Number, m01:Number;
    public var m10:Number, m11:Number;
    
    public function Matrix22(_m00:Number = 0, _m01:Number = 0, _m10:Number = 0, _m11:Number = 0)
    {
        m00=_m00; m01=_m01;
        m10=_m10; m11=_m11;
    }
    public function setM(a:Matrix22):void
    {
        m00=a.m00; m01=a.m01;
        m10=a.m10; m11=a.m11;
    }
    public function setXY(_m00:Number, _m01:Number, _m10:Number, _m11:Number):void
    {
        m00=_m00; m01=_m01;
        m10=_m10; m11=_m11;
    }
    public function isZero():Boolean
    {
        return m00==0 && m01==0 && m10==0 && m11==0;
    }
    public function isIdentity():Boolean
    {
        return m00==1 && m01==0 && m10==0 && m11==1;
    }
    public function minus():void
    {
        m00=-m00; m01=-m01;
        m10=-m10; m11=-m11;
    }
    public function multiplyN(a:Number):void
    {
        m00*=a; m01*=a;
        m10*=a; m11*=a;
    }
    public function multiplyM(a:Matrix22):void
    {
        var _m00:Number = m00*a.m00+m01*a.m10;
        var _m01:Number = m00*a.m01+m01*a.m11;
        var _m10:Number = m10*a.m00+m11*a.m10;
        var _m11:Number = m10*a.m01+m11*a.m11;
        m00=_m00; m01=_m01;
        m10=_m10; m11=_m11;
    }
    public function divide(a:Number):void
    {
        m00/=a; m01/=a;
        m10/=a; m11/=a;
    }
    public function add(a:Matrix22):void
    {
        m00+=a.m00; m01+=a.m01;
        m10+=a.m10; m11+=a.m11;
    }
    public function subtract(a:Matrix22):void
    {
        m00-=a.m00; m01-=a.m01;
        m10-=a.m10; m11-=a.m11;
    }
    public function equal(a:Matrix22):Boolean
    {
        return m00==a.m00 && m01==a.m01 && m10==a.m10 && m11==a.m11;
    }
    public function notEqual(a:Matrix22):Boolean
    {
        return m00!=a.m00 || m01!=a.m01 || m10!=a.m10 || m11!=a.m11;
    }
}

class Vector2
{
    public var x:Number;
    public var y:Number;
    
    public function Vector2(_x:Number = 0, _y:Number = 0)
    {
        x = _x;
        y = _y;
    }
    public function setV(a:Vector2):void
    {
        x = a.x;
        y = a.y;
    }
    public function setXY(_x:Number, _y:Number):void
    {
        x = _x;
        y = _y;
    }
    public function length():Number
    {
        return Math.sqrt(x*x+y*y);
    }
    public function length2():Number
    {
        return x*x+y*y;
    }
    public function isZero():Boolean
    {
        return x==0 && y==0;
    }
    public function normalize():void
    {
        var a:Number = Math.sqrt(x*x+y*y);
        x /= a;
        y /= a;
    }
    public function dot(a:Vector2):Number
    {
        return x*a.x+y*a.y;
    }
    public function minus():void
    {
        x = -x;
        y = -y;
    }
    public function multiplyN(a:Number):void
    {
        x *= a;
        y *= a;
    }
    public function multiplyMV(a:Matrix22):void
    {
        var _x:Number = a.m00*x+a.m01*y;
        var _y:Number = a.m10*x+a.m11*y;
        x = _x;
        y = _y;
    }
    public function multiplyVM(a:Matrix22):void
    {
        var _x:Number = x*a.m00+y*a.m10;
        var _y:Number = x*a.m01+y*a.m11;
        x = _x;
        y = _y;
    }
    public function divide(a:Number):void
    {
        x /= a;
        y /= a;
    }
    public function add(a:Vector2):void
    {
        x += a.x;
        y += a.y;
    }
    public function subtract(a:Vector2):void
    {
        x -= a.x;
        y -= a.y;
    }
    public function equal(a:Vector2):Boolean
    {
        return x==a.x && y==a.y;
    }
    public function notEqual(a:Vector2):Boolean
    {
        return x!=a.x || y!=a.y;
    }
}

class Segment
{
    public var a:Vector2 = new Vector2();
    public var b:Vector2 = new Vector2();
    private var e:Number = 0.9;            //跳ね返り係数 ////////////////////////////
    
    public function Segment(ax:Number, ay:Number, bx:Number, by:Number)
    {
        a.setXY(ax, ay);
        b.setXY(bx, by);
    }
    public function collision(ball:Ball):void
    {
        var ab:Vector2 = new Vector2();
        var ax:Vector2 = new Vector2();
        var x:Vector2 = new Vector2(ball.x, ball.y);
        var n:Vector2 = new Vector2();
        var k:Number;
        var i:Number, j:Number;
        var collision:Boolean = false;
        
        ab.setV(b);
        ab.subtract(a);
        ax.setV(x);
        ax.subtract(a);
        k = ab.dot(ax);
        
        if(k < 0) // point A
        {
            if(ax.length2() <= ball.r*ball.r)
            {
                n.setV(ax);
                collision = true;
            }
        }
        else if(k > ab.length2()) // point B
        {
            n.setV(x);
            n.subtract(b);
            if(n.length2() <= ball.r*ball.r)
            {
                collision = true;
            }
        }
        else // line AB
        {
            k /= ab.length2();
            ab.multiplyN(k);
            n.setV(x);
            n.subtract(a);
            n.subtract(ab);
            if(n.length2() <= ball.r*ball.r)
            {
                collision = true;
            }
        }
        
        if(collision)
        {
            k = ball.r-n.length();
            n.normalize();
            // position
            x.setV(n);
            x.multiplyN((1+e)*k);
            ball.x += x.x;
            ball.y += x.y;
            // velocity
            var s:Matrix22 = new Matrix22(n.y, n.x, -n.x, n.y);
            var si:Matrix22 = new Matrix22(n.y, -n.x, n.x, n.y);
            x.setXY(ball.vx, ball.vy);
            x.multiplyMV(si);
            x.y = -e*x.y;
            i = -2.0*(e+1.0)*(-x.x)/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
            j = (2.0-e)*(-x.x)/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
            ball.vrotation = i;
            x.x = -j;
            x.multiplyMV(s);
            
            ball.vx = x.x;
            ball.vy = x.y;
        }
        /*
        
                ball.y = (e+1.0)*(0.480-ball.r)-e*ball.y;
                ball.vy = -e*ball.vy;
                m = -2.0*(e+1.0)*ball.vx/3.0/ball.r + (1.0-2.0*e)*ball.vrotation/3.0;
                n = (2.0-e)*ball.vx/3.0 - (1.0+e)*ball.vrotation*ball.r/3.0;
                ball.vrotation = m;
                ball.vx = n;
        */
    }
}