Beautifl - Flash Gallery

Preview

[Study] Hydrodynamics
alumican_net 2010年4月26日 MIT License
?
漁ってたらなんか出てきたので置いておく  
  
マウス押しっぱなしでパーティクル生成する  
create particle : MouseDown
      /**
 * 漁ってたらなんか出てきたので置いておく
 * 
 * マウス押しっぱなしでパーティクル生成する
 * create particle : MouseDown
 */
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.BevelFilter;
    import flash.filters.BlurFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.geom.Vector3D;
    import net.hires.debug.Stats;
    import frocessing.color.ColorHSV;
    
    /**
     * Main
     * 
     * @author alumican
     */
    public class Main extends Sprite
    {
        //----------------------------------------
        //CLASS CONSTANTS
        
        private const SPH_RESTDENSITY:Number = 600.0;
        private const SPH_INTSTIFF:Number    = 1.0;
        private const SPH_PMASS:Number       = 0.00020543;
        private const SPH_SIMSCALE:Number    = 0.004;
        private const H:Number               = 0.01;
        private const H2:Number              = H * H;
        private const PI:Number              = Math.PI;
        private const DT:Number              = 0.004;
        private const SPH_VISC:Number        = 0.2;
        private const SPH_LIMIT:Number       = 200.0;
        private const SPH_LIMIT2:Number      = SPH_LIMIT * SPH_LIMIT;
        private const SPH_RADIUS:Number      = 0.004;
        private const SPH_EPSILON:Number     = 0.00001;
        private const SPH_EXTSTIFF:Number    = 10000.0;
        private const SPH_EXTDAMP:Number     = 256.0;
        private const SPH_PDIST:Number       = Math.pow(SPH_PMASS / SPH_RESTDENSITY, 1.0 / 3.0);
        
        private const MIN:Vector3            = new Vector3( 0.0,  0.0, -10.0);
        private const MAX:Vector3            = new Vector3(20.0, 20.0,  10.0);
        private const INIT_MIN:Vector3       = new Vector3( 0.0,  0.0, -10.0);
        private const INIT_MAX:Vector3       = new Vector3(10.0, 20.0,  10.0);
        private const Poly6Kern:Number       = 315.0 / (64.0 * PI * Math.pow(H, 9));
        private const SpikyKern:Number       = -45.0 / (       PI * Math.pow(H, 6));
        private const LapKern:Number         =  45.0 / (       PI * Math.pow(H, 6));
        private const VTERM:Number           = LapKern * SPH_VISC;
        
        private const AXIS_Z0:Vector3        = new Vector3( 0,  0,  1);
        private const AXIS_Z1:Vector3        = new Vector3( 0,  0, -1);
        private const AXIS_X0:Vector3        = new Vector3( 1,  0,  0);
        private const AXIS_X1:Vector3        = new Vector3(-1,  0,  0);
        private const AXIS_Y0:Vector3        = new Vector3( 0,  1,  0);
        private const AXIS_Y1:Vector3        = new Vector3( 0, -1,  0);
        
        private const GRAVITY:Vector3        = new Vector3(0.0, 9.8, 0.0);
        
        
        
        
        //----------------------------------------
        //VARIABLES
        
        /**
         * イテレータ
         */
        private var _first:Particle;
        private var _last:Particle;
        
        /**
         * パーティクル数
         */
        private var _particleCount:uint;
        
        /**
         * 表示
         */
        private var _canvas:BitmapData;
        private var _canvasRect:Rectangle;
        private var _pallet:Array;
        
        private var _blurFilter:BlurFilter   = new BlurFilter(32, 32, 2);
        private var _bevelFilter:BevelFilter = new BevelFilter(5, 45, 0xeeeeee, 1, 0x999999, 1, 25, 25, 1.5, 2);
        
        private var _clearBitmapData:BitmapData;
        private var _whiteBitmapData:BitmapData;
        private var _blobBitmapData:BitmapData;
        
        private const ZEROS:Point = new Point(0, 0);
        
        /**
         * ボール
         */
        private var _container:Sprite;
        
        /**
         * マウスダウン中であればtrue
         */
        private var _isMouseDown:Boolean;
        
        private var _colorHSV:ColorHSV;
        
        
        
        
        
        //----------------------------------------
        //STAGE INSTANCES
        
        
        
        
        
        //----------------------------------------
        //METHODS
        
        /**
         * コンストラクタ
         */
        public function Main():void 
        {
                        Wonderfl.disable_capture();
                       // Wonderfl.capture_delay(10);
                        
            var w:uint = 465;
            var h:uint = 465;
            
            stage.scaleMode = StageScaleMode.SHOW_ALL;
            stage.frameRate = 60;
            
            _canvas = new BitmapData(w, h, false, 0xffffff);
            _canvasRect = _canvas.rect;
            addChild( new Bitmap(_canvas) );
            
            _container = new Sprite();
            
            _pallet = new Array();
            for (var i:uint = 0; i < 0x100; i++)
            {
                _pallet.push((i < 30) ? 0x000000 : 0xff000000);
            }
            
            _clearBitmapData = new BitmapData(w, h, true, 0x00ffffff);
            _whiteBitmapData = new BitmapData(w, h, false, 0xffffff);
            _blobBitmapData  = new BitmapData(w, h, true);
            
            
            
            
            
            _createParticles();
            addEventListener(Event.ENTER_FRAME, _update);
            
        //    var stats:Stats = addChild( new Stats() ) as Stats;
        //    stats.x = stage.stageWidth - 70;
            
            _isMouseDown = false;
            stage.addEventListener(MouseEvent.MOUSE_DOWN, _stageMouseDownHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, _stageMouseUpHandler);
        }
        
        
        
        
        
        /**
         * 初期パーティクルの生成
         */
        private function _createParticles():void
        {
            var p0:Particle,
                p1:Particle,
                d:Number = SPH_PDIST / SPH_SIMSCALE * 0.8, //0.87
                initMin:Vector3 = INIT_MIN,
                initMax:Vector3 = INIT_MAX,
                x:Number,
                y:Number,
                z:Number,
                i:uint,
                n:uint,
                tmp:Array = new Array();
            
            _colorHSV = new ColorHSV(0, 0.7, 0.9);
            
            //パーティクル生成
            for (x = initMin.x + d; x <= initMax.x - d; x += d)
            for (y = initMin.y + d; y <= initMax.y - d; y += d)
        //    for (z = initMin.z + d; z <= initMax.z - d; z += d)
            {
                z = 0;
                
                p0 = new Particle(x, y, z);
                
                _colorHSV.h += 0.1;
                p0.createBall(10, _colorHSV.value);
                _container.addChild(p0.ball);
                
                tmp.push(p0);
            }
            
            //パーティクル数
            _particleCount = tmp.length;
            
            //イテレータ
            _first = tmp[0];
            _last  = tmp[_particleCount - 1];
            
            //リンクリスト生成
            n = _particleCount - 1;
            for (i = 0; i < n; ++i) 
            {
                p0 = tmp[i    ];
                p1 = tmp[i + 1];
                
                p0.next = p1;
                p1.prev = p0;
            }
        }
        
        private function _generateParticle():void
        {
            //generate
            var px:Number = mouseX / 20;
            var py:Number = mouseY / 20;
            
            var p:Particle = new Particle(px, py, 0);
            
            _colorHSV.h += 0.5;
            p.createBall(Math.random() * 5 + 7.5, _colorHSV.value);
            _container.addChild(p.ball);
            
            _last.next = p;
            p.prev = _last;
            _last = p;
            
            ++_particleCount;
            
            //delete
            p = _first;
            _container.removeChild(p.ball);
            _first = _first.next;
        }
        
        
        
        
        
        /**
         * アップデータ
         * @param    e
         */
        private function _update(e:Event):void 
        {
            _simulation();
            _draw();
        }
        
        
        
        
        
        /**
         * シミュレーション
         */
        private function _simulation():void
        {
            if (_isMouseDown)
            {
                _generateParticle();
            }
            
            _calcAmount();
            _calcForce();
            _calcAdvance();
        }
        
        /**
         * 密度の算出
         */
        private function _calcAmount():void
        {
            var h2:Number             = H2,
                sphSimscale:Number    = SPH_SIMSCALE,
                sphPmass:Number       = SPH_PMASS,
                sphIntstiff:Number    = SPH_INTSTIFF,
                sphRestdensity:Number = SPH_RESTDENSITY,
                poly6Kern:Number      = Poly6Kern,
                sum:Number,
                r2:Number,
                c:Number,
                dr:Vector3,
                pi:Particle = _first,
                pj:Particle;
            
            do
            {
                sum = 0.0;
                pj  = _first;
                
                do
                {
                    if (pi === pj) continue;
                    
                    dr = Vector3.subtraction(pi.pos, pj.pos).multiScalar(sphSimscale);
                    
                    r2 = Vector3.norm2(dr);
                    
                    if (h2 > r2)
                    {
                        c = h2 - r2;
                        sum += c * c * c;
                    }
                }
                while (pj = pj.next);
                
                pi.rho = sum * sphPmass * poly6Kern;
                pi.prs = (pi.rho - sphRestdensity) * sphIntstiff;
                pi.rho = 1.0 / pi.rho;
            }
            while (pi = pi.next);
        }
        
        /**
         * 力の算出
         */
        private function _calcForce():void
        {
            var sphSimscale:Number = SPH_SIMSCALE,
                sphVisc:Number     = SPH_VISC,
                h:Number           = H,
                h2:Number          = H2,
                spikyKern:Number   = SpikyKern,
                lapKern:Number     = LapKern,
                vterm:Number       = VTERM,
                pterm:Number,
                r:Number,
                r2:Number,
                c:Number,
                dr:Vector3,
                force:Vector3,
                fcurr:Vector3,
                pi:Particle = _first,
                pj:Particle,
                mx:Number = (mouseX / stage.stageWidth  - 0.5) * 2 / sphSimscale,
                my:Number = (mouseY / stage.stageHeight - 0.5) * 2 / sphSimscale,
                md:Number,
                pix:Number,
                piy:Number,
                dix:Number,
                diy:Number;
            
            do
            {
                force = new Vector3();
                pj = _first;
                
                do
                {
                    if (pi === pj) continue;
                    
                    if (pi.pos.eq(pj.pos)) continue;
                    
                    dr = Vector3.subtraction(pi.pos, pj.pos);
                    dr.multiScalar(sphSimscale);
                    
                    r2 = Vector3.norm2(dr);
                    
                    if (h2 > r2)
                    {
                        r = Math.sqrt(r2);
                        c = h - r;
                        
                        pterm = -0.5 * c * spikyKern * (pi.prs + pj.prs) / r;
                        
                        fcurr = Vector3.multiplyScalar(dr, pterm).add( Vector3.subtraction(pj.vel, pi.vel).multiScalar(vterm) );
                        fcurr.multiScalar(c * pi.rho * pj.rho);
                        
                        force.add(fcurr);
                    }
                    
                    //マウス
                    if (h2 > r2)
                    {
                        pix = pi.pos.x;
                        piy = pi.pos.y;
                        
                        dix = pix - mx;
                        diy = piy - my;
                        
                        md = Math.sqrt(dix * dix + diy * diy);
                        
                        force.x -= 10000 * (dix / md);
                        force.y -= 10000 * (diy / md);
                    }
                }
                while (pj = pj.next);
                
                pi.f = force;
            }
            while (pi = pi.next);
        }
        
        /**
         * 粒子の移動
         */
        private function _calcAdvance():void
        {
            var sphPmass:Number    = SPH_PMASS,
                sphLimit:Number    = SPH_LIMIT,
                sphLimit2:Number   = SPH_LIMIT2,
                sphRadius:Number   = SPH_RADIUS,
                sphSimscale:Number = SPH_SIMSCALE,
                sphEpsilon:Number  = SPH_EPSILON,
                sphExtstiff:Number = SPH_EXTSTIFF,
                sphExtdamp:Number  = SPH_EXTDAMP,
                dt:Number          = DT,
                min:Vector3        = MIN,
                max:Vector3        = MAX,
                axisZ0:Vector3     = AXIS_Z0,
                axisZ1:Vector3     = AXIS_Z1,
                axisX0:Vector3     = AXIS_X0,
                axisX1:Vector3     = AXIS_X1,
                axisY0:Vector3     = AXIS_Y0,
                axisY1:Vector3     = AXIS_Y1,
                g:Vector3          = GRAVITY,
                accel:Vector3,
                speed:Number,
                diff:Number,
                adj:Number,
                p:Particle = _first;
            
            do
            {
                accel = Vector3.multiplyScalar(p.f, sphPmass);
                speed = Vector3.norm2(accel);
                
                if (speed > sphLimit2)
                {
                    accel.multiScalar(sphLimit / Math.sqrt(speed));
                }
                
                // Z-axis walls
                /*
                diff = 2.0 * sphRadius - (p.pos.z - min.z) * sphSimscale;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisZ0, p.vel);
                    accel.add(Vector3.multiplyScalar(axisZ0, adj));
                }
                
                diff = 2.0 * sphRadius - (max.z - p.pos.z) * sphSimscale;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisZ1, p.vel);
                    accel.add(Vector3.multiplyScalar(axisZ1, adj));
                }
                */
                
                // X-axis walls
                diff = 2.0 * sphRadius - (p.pos.x - min.x) * sphSimscale + 0.005;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisX0, p.vel);
                    accel.add(Vector3.multiplyScalar(axisX0, adj));
                }
                
                diff = 2.0 * sphRadius - (max.x - p.pos.x) * sphSimscale - 0.005;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisX1, p.vel);
                    accel.add(Vector3.multiplyScalar(axisX1, adj));
                }
                
                // Y-axis walls
                diff = 2.0 * sphRadius - (p.pos.y - min.y) * sphSimscale + 0.005;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisY0, p.vel);
                    accel.add(Vector3.multiplyScalar(axisY0, adj));
                }
                
                diff = 2.0 * sphRadius - (max.y - p.pos.y) * sphSimscale - 0.005;
                if (diff > sphEpsilon)
                {
                    adj = sphExtstiff * diff - sphExtdamp * Vector3.dot(axisY1, p.vel);
                    accel.add(Vector3.multiplyScalar(axisY1, adj));
                }
                
                accel.add(g);
                p.vel.add(accel.multiScalar(dt));
                p.pos.add(p.vel.multiScalar(dt / sphSimscale));
            }
            while (p = p.next);
        }
        
        
        
        
        
        /**
         * 描画
         */
        private function _draw():void
        {
            //_canvas.lock();
            //_canvas.fillRect(_canvasRect, 0xffffff);
            var p:Particle = _first;
            do
            {
                p.ball.x = p.pos.x * 20;
                p.ball.y = p.pos.y * 20;
                
                //_canvas.setPixel(p.pos.x * 20, p.pos.y * 20, 0x000000);
            }
            while (p = p.next);
            
            /*
            _canvas.draw(_container);
            _canvas.applyFilter(_canvas, _canvasRect, ZEROS, _blurFilter);
            */
            
            _blobBitmapData.lock();
            _blobBitmapData.copyPixels(_clearBitmapData, _canvasRect, ZEROS);
            _blobBitmapData.draw(_container);
            _blobBitmapData.applyFilter(_blobBitmapData, _canvasRect, ZEROS, _blurFilter);
            _blobBitmapData.paletteMap(_blobBitmapData, _canvasRect, ZEROS, null, null, null, _pallet);
            //_blobBitmapData.applyFilter(_blobBitmapData, _canvasRect, ZEROS, _bevelFilter);
            _blobBitmapData.unlock();
            
            _canvas.lock();
            _canvas.copyPixels(_whiteBitmapData, _canvasRect, ZEROS);
            _canvas.copyPixels(_blobBitmapData, _canvasRect, ZEROS);
            _canvas.unlock();
        }
        
        
        
        
        
        private function _stageMouseDownHandler(e:MouseEvent):void 
        {
            _isMouseDown = true;
        }
        
        private function _stageMouseUpHandler(e:MouseEvent):void 
        {
            _isMouseDown = false;
        }
    }
}





/**
 * Vector3
 * @author alumican
 */
class Vector3
{
    
    //----------------------------------------
    //CLASS CONSTANTS
    
    
    
    
    
    //----------------------------------------
    //VARIABLES
    
    public var x:Number;
    public var y:Number;
    public var z:Number;
    
    
    
    
    
    //----------------------------------------
    //STAGE INSTANCES
    
    
    
    
    
    //----------------------------------------
    //METHODS
    
    /**
     * コンストラクタ
     */
    public function Vector3(x:Number = 0, y:Number = 0, z:Number = 0):void 
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    
    
    
    
    
    /**
     * == vec
     */
    public function eq(vec:Vector3):Boolean
    {
        return (x == vec.x && y == vec.y && z == vec.z);
    }
    
    /**
     * += vec
     */
    public function add(vec:Vector3):Vector3
    {
        x += vec.x;
        y += vec.y;
        z += vec.z;
        return this;
    }
    
    /**
     * -= vec
     */
    public function sub(vec:Vector3):Vector3
    {
        x -= vec.x;
        y -= vec.y;
        z -= vec.z;
        return this;
    }
    
    /**
     * *= vec
     */
    public function multi(vec:Vector3):Vector3
    {
        x *= vec.x;
        y *= vec.y;
        z *= vec.z;
        return this;
    }
    
    /**
     * /= value
     */
    public function div(vec:Vector3):Vector3
    {
        if (vec.x == 0 || vec.y == 0 || vec.z == 0) throw new ArgumentError("division by 0");
        x /= vec.x;
        y /= vec.y;
        z /= vec.z;
        return this;
    }
    
    /**
     * %= vec
     */
    public function mod(vec:Vector3):Vector3
    {
        x %= vec.x;
        y %= vec.y;
        z %= vec.z;
        return this;
    }
    
    /**
     * += value
     */
    public function addScalar(value:Number):Vector3
    {
        x += value;
        y += value;
        z += value;
        return this;
    }
    
    /**
     * -= value
     */
    public function subScalar(value:Number):Vector3
    {
        x -= value;
        y -= value;
        z -= value;
        return this;
    }
    
    /**
     * *= value
     */
    public function multiScalar(value:Number):Vector3
    {
        x *= value;
        y *= value;
        z *= value;
        return this;
    }
    
    /**
     * /= value
     */
    public function divScalar(value:Number):Vector3
    {
        if (value == 0) throw new ArgumentError("division by 0");
        x /= value;
        y /= value;
        z /= value;
        return this;
    }
    
    /**
     * %= value
     */
    public function modScalar(value:Number):Vector3
    {
        x %= value;
        y %= value;
        z %= value;
        return this;
    }
    
    /**
     * -
     */
    public function inv():Vector3
    {
        x = -x;
        y = -y;
        z = -z;
        return this;
    }
    
    /**
     * 複製
     */
    public function clone():Vector3
    {
        return new Vector3(x, y, z);
    }
    
    
    
    
    
    /**
     * a == b
     */
    static public function equal(a:Vector3, b:Vector3):Boolean
    {
        return (a.x == b.x && a.y == b.y && a.z == b.z);
    }
    
    /**
     * a + b
     */
    static public function addition(a:Vector3, b:Vector3):Vector3
    {
        return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
    }
    
    /**
     * a - b
     */
    static public function subtraction(a:Vector3, b:Vector3):Vector3
    {
        return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
    }
    
    /**
     * a * b
     */
    static public function multiply(a:Vector3, b:Vector3):Vector3
    {
        return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
    }
    
    /**
     * a / b
     */
    static public function division(a:Vector3, b:Vector3):Vector3
    {
        if (b.x == 0 || b.y == 0 || b.z == 0) throw new ArgumentError("division by 0");
        return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
    }
    
    /**
     * a % b
     */
    static public function modulo(a:Vector3, b:Vector3):Vector3
    {
        return new Vector3(a.x % b.x, a.y % b.y, a.z % b.z);
    }
    
    /**
     * a + value
     */
    static public function additionScalar(a:Vector3, value:Number):Vector3
    {
        return new Vector3(a.x + value, a.y + value, a.z + value);
    }
    
    /**
     * a - value
     */
    static public function subtractionScalar(a:Vector3, value:Number):Vector3
    {
        return new Vector3(a.x - value, a.y - value, a.z - value);
    }
    
    /**
     * a * value
     */
    static public function multiplyScalar(a:Vector3, value:Number):Vector3
    {
        return new Vector3(a.x * value, a.y * value, a.z * value);
    }
    
    /**
     * a / value
     */
    static public function divisionScalar(a:Vector3, value:Number):Vector3
    {
        if (value == 0) throw new ArgumentError("division by 0");
        return new Vector3(a.x / value, a.y / value, a.z / value);
    }
    
    /**
     * a % value
     */
    static public function moduloScalar(a:Vector3, value:Number):Vector3
    {
        return new Vector3(a.x % value, a.y % value, a.z % value);
    }
    
    /**
     * -a
     */
    static public function invert(a:Vector3):Vector3
    {
        return new Vector3(-a.x, -a.y, -a.z);
    }
    
    /**
     * 内積
     */
    static public function dot(a:Vector3, b:Vector3):Number
    {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    
    /**
     * 大きさの二乗
     */
    static public function norm2(a:Vector3):Number
    {
        return a.x * a.x + a.y * a.y + a.z * a.z;
    }
    
    /**
     * 大きさ
     */
    static public function norm(a:Vector3):Number
    {
        return Math.sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
    }
    
    
    
    
    
    /**
     * toString
     */
    public function toString():String
    {
        return "x = " + String(x) + ", y = " + String(y) + ", z = " + String(z);
    }
}





import flash.display.Sprite;
/**
 * Particle
 * 
 * @author alumican
 */
class Particle
{
    //----------------------------------------
    //CLASS CONSTANTS
    
    
    
    
    
    //----------------------------------------
    //VARIABLES
    
    /**
     * 座標
     */
    public var pos:Vector3;
    
    /**
     * 速度
     */
    public var vel:Vector3;
    
    /**
     * 力
     */
    public var f:Vector3;
    
    /**
     * 密度
     */
    public var rho:Number;
    
    /**
     * 圧力
     */
    public var prs:Number;
    
    /**
     * イテレータ
     */
    public var prev:Particle;
    public var next:Particle;
    
    /**
     * 表示オブジェクト
     */
    public var ball:Ball;
    
    
    
    
    
    //----------------------------------------
    //STAGE INSTANCES
    
    
    
    
    
    //----------------------------------------
    //METHODS
    
    /**
     * コンストラクタ
     */
    public function Particle(x:Number = 0, y:Number = 0, z:Number = 0):void
    {
        pos  = new Vector3(x, y, z);
        vel  = new Vector3(0, 0, 0);
        f    = new Vector3(0, 0, 0);
        rho  = 0;
        prs  = 0;
        next = null;
    }
    
    public function createBall(radius:Number = 10, color:uint = 0x0):void
    {
        ball = new Ball(radius, color);
    }
}





import flash.display.Sprite;

/**
 * Ball
 * 
 * @author alumican
 */
class Ball extends Sprite
{
    
    //----------------------------------------
    //CLASS CONSTANTS
    
    
    
    
    
    //----------------------------------------
    //VARIABLES
    
    
    
    
    
    //----------------------------------------
    //STAGE INSTANCES
    
    
    
    
    
    //----------------------------------------
    //METHODS
    
    /**
     * コンストラクタ
     */
    public function Ball(radius:Number = 10, color:uint = 0x0):void 
    {
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, radius);
        graphics.endFill();
    }
}