Beautifl - Flash Gallery

Preview

forked from: パーティクルの応用で弾幕3 - 超最適化 - 凝視注意
NOB_Q 2009年8月31日 MIT License
?
コードのリファクタリング & 最適化  
Nicolasが最適化してくれました。  
http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51  
BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!  
めっちゃ早いよ!これ!  
by coppieee  
  
さらに最適化!  
http://wonderfl.net/code/9dcd5e428a43c4b20f69f86873f2831fa9ec32f3  
に触発されて、私も最適化してみた。Linked listは使いたくなかったので別の方法で。  
これでもか!ってぐらいがんばった。  
  
Particleのプール用意して、  
削除のところ工夫して、  
回転の計算のアルゴリズム変更して、  
とかもろもろ。  
  
弾の大きさを変更したのはオマケ。(オマケなんだけど、小さければ小さいほど速くなるよ。)  
きっとこれ以上の最適化は無理だと思うよ!  
  
  
_canvas.copyPixels()のところを別の描画のアルゴリズムで置き換えたら、あるいはもっと速く・・・。  
by coppieee  
  
 凝視注意
      // forked from coppieee's パーティクルの応用で弾幕3 - 超最適化
// forked from coppieee's forked from: パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's 弾幕 - パーティクルの応用で弾幕

/*
 * コードのリファクタリング & 最適化
 * Nicolasが最適化してくれました。
 * http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51
 * BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!
 * めっちゃ早いよ!これ!
 * by coppieee
 */
/*
 * さらに最適化!
 * http://wonderfl.net/code/9dcd5e428a43c4b20f69f86873f2831fa9ec32f3
 * に触発されて、私も最適化してみた。Linked listは使いたくなかったので別の方法で。
 * これでもか!ってぐらいがんばった。
 * 
 * Particleのプール用意して、
 * 削除のところ工夫して、
 * 回転の計算のアルゴリズム変更して、
 * とかもろもろ。
 * 
 * 弾の大きさを変更したのはオマケ。(オマケなんだけど、小さければ小さいほど速くなるよ。)
 * きっとこれ以上の最適化は無理だと思うよ!
 * 
 * 
 * _canvas.copyPixels()のところを別の描画のアルゴリズムで置き換えたら、あるいはもっと速く・・・。
 * by coppieee
 */
/**
 * 凝視注意
 */ 
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import net.hires.debug.Stats;
    
    [SWF(width="512",height="512", frameRate="60" )]
    public class PShooting extends Sprite 
    {
        //1fpsあたりの弾の生成数
        public static const BULLET_COUNT:int = 24;
        
        public static const WIDTH:Number = 512;
        public static const HEIGHT:Number = 512;
        
        //弾のビットマップキャッシュ
        private const COLOR_NUM:int = 24;
        private var _bulletImg:Vector.<BitmapData> = new Vector.<BitmapData>(COLOR_NUM);
        private var _bigColor:Vector.<int> = new Vector.<int>(COLOR_NUM);
        private var _smallColor:Vector.<int> = new Vector.<int>(COLOR_NUM);
        
        //キャンバス
        private var _canvas:BitmapData;
        //パーティクルリスト(Vector#unshift()がバグってて使えないので、しょうがないからArray使う。)
        private var _particles:/*Particle*/Array;
        //敵。というか弾の再生位置。
        private var _enemy:Particle;
        //パーティクルプール(いらなくなったパーティクルを溜めとくとこ)
        private var _particlesPool:Vector.<Particle>;
        
        private var _colorIndexCount:int = 0;
        
        public function PShooting()
        {
            Wonderfl.capture_delay( 7 );
            
            //キャンバスの生成
            _canvas = new BitmapData(WIDTH, HEIGHT,false,0x000000);
            var cb:Bitmap = new Bitmap(_canvas);
            addChild(cb);
            
            _particles = [];
            _enemy = new Particle();
            _particlesPool = new Vector.<Particle>();

            
            var seq:int = 0;
            _bigColor[seq] = 0xFF0000;    _smallColor[seq] = 0x550000;    seq++;
            _bigColor[seq] = 0xFF0040;    _smallColor[seq] = 0x550015;    seq++;
            _bigColor[seq] = 0xFF007F;    _smallColor[seq] = 0x55002B;    seq++;
            _bigColor[seq] = 0xFF00C0;    _smallColor[seq] = 0x550040;    seq++;
            _bigColor[seq] = 0xFF00FF;    _smallColor[seq] = 0x550055;    seq++;
            _bigColor[seq] = 0xC000FF;    _smallColor[seq] = 0x400055;    seq++;
            _bigColor[seq] = 0x7F00FF;    _smallColor[seq] = 0x2B0055;    seq++;
            _bigColor[seq] = 0x4000FF;    _smallColor[seq] = 0x150055;    seq++;
            _bigColor[seq] = 0x0000FF;    _smallColor[seq] = 0x000055;    seq++;
            _bigColor[seq] = 0x0040FF;    _smallColor[seq] = 0x001555;    seq++;
            _bigColor[seq] = 0x007FFF;    _smallColor[seq] = 0x002B55;    seq++;
            _bigColor[seq] = 0x00C0FF;    _smallColor[seq] = 0x004055;    seq++;
            _bigColor[seq] = 0x00FFFF;    _smallColor[seq] = 0x005555;    seq++;
            _bigColor[seq] = 0x00FFC0;    _smallColor[seq] = 0x005540;    seq++;
            _bigColor[seq] = 0x00FF7F;    _smallColor[seq] = 0x00552B;    seq++;
            _bigColor[seq] = 0x00FF40;    _smallColor[seq] = 0x005515;    seq++;
            _bigColor[seq] = 0x00FF00;    _smallColor[seq] = 0x005500;    seq++;
            _bigColor[seq] = 0x40FF00;    _smallColor[seq] = 0x155500;    seq++;
            _bigColor[seq] = 0x7FFF00;    _smallColor[seq] = 0x2B5500;    seq++;
            _bigColor[seq] = 0xC0FF00;    _smallColor[seq] = 0x405500;    seq++;
            _bigColor[seq] = 0xFFFF00;    _smallColor[seq] = 0x555500;    seq++;
            _bigColor[seq] = 0xFFC000;    _smallColor[seq] = 0x554000;    seq++;
            _bigColor[seq] = 0xFF7F00;    _smallColor[seq] = 0x552B00;    seq++;
            _bigColor[seq] = 0xFF4000;    _smallColor[seq] = 0x551500;    seq++;

            
            //弾のBitmapの生成
            var shape:Shape;
            var g:Graphics;
            for (var i:int = 0; i < COLOR_NUM; i++) {
                //Shapeに円を書く。
                shape = new Shape();
                g = shape.graphics;
                g.beginFill(_bigColor[i], 0.5);
                g.drawCircle(8, 8, 8);
                g.beginFill(_smallColor[i]);
                g.drawCircle(8, 8, 4);
                g.endFill();
                //BitmapDataにdraw()
                _bulletImg[i] = new BitmapData(shape.width, shape.height, true, 0xFFFFFF);
                _bulletImg[i].draw(shape);
            }
            
            //Statsの生成
            addChild(new Stats());
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            
            //particlsの個数表示用のTextField生成
            var tf:TextField = new TextField();
            tf.y = 100;
            tf.textColor = 0xFFFFFF;
            tf.background = true;
            tf.backgroundColor = 0x000000;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.multiline = true;
            addChild(tf);
            addEventListener(Event.ENTER_FRAME, function(e:Event):void {
                tf.text = "bullets:" + _particles.length +"\n pool:"+_particlesPool.length ;
            });
        }
        private var _radian:Number = 0;
        
        private function onEnterFrame(e:Event):void
        {
            _canvas.lock();
            
            var ct:ColorTransform = new ColorTransform (0.9, 0.9, 0.95);
            _canvas.colorTransform(_canvas.rect, ct);
            //下の方が軽いけど、見た目が悪くなる。
            //_canvas.fillRect(_canvas.rect, 0x000000);
            
            //弾の生成場所をマウスのところへ移動
            _enemy.vx = (stage.mouseX - _enemy.x) * 0.05;
            _enemy.vy = (stage.mouseY - _enemy.y) * 0.05;
            _enemy.x += _enemy.vx;
            _enemy.y += _enemy.vy;
            
            //回転
            _radian += (Math.PI / 180) *62.1;
            var bRadian:Number = _radian;
            //弾の生成
            for (var i:int = 0; i <BULLET_COUNT; i++ )
            {
                var vx:Number = Math.cos(bRadian) * 10;
                var vy:Number = Math.sin(bRadian) * 10;
                var newP:Particle;
                if (_particlesPool.length != 0)
                {
                    newP = _particlesPool.pop();
                }else{
                    newP = new Particle();
                }
                newP.x = _enemy.x;
                newP.y = _enemy.y;
                newP.vx = vx;
                newP.vy = vy;
                newP.ci = _colorIndexCount % COLOR_NUM;
                _particles.unshift(newP);
                
                bRadian += Math.PI * 2 / BULLET_COUNT;
            }
            _colorIndexCount++;
                
            
            //必要な計算はforループの前にしておく。
            var bulletRect:Rectangle = _bulletImg[0].rect;
            var bulletPoint:Point = new Point();
            
            var phi:Number = Math.PI / 180 * 80;
            var cosPhi:Number = Math.cos(phi) * 0.02; //0.02はオマケ
            var sinPhi:Number = Math.sin(phi) * 0.02;
            
            var bWidth_2:int = _bulletImg[0].width / 2;
            var bHeight_2:int = _bulletImg[0].height / 2;
            var xMin:int = - bWidth_2 / 2;
            var yMin:int = - bHeight_2 / 2;
            var xMax:int = bWidth_2 + WIDTH;
            var yMax:int = bHeight_2 + HEIGHT;
            
            //弾の移動
            for (var j:int = _particles.length - 1; j != -1 ;j--)
            {
                var p:Particle = _particles[j];
                
                //ベクトルうめぇww
                p.ax = p.vx * cosPhi - p.vy * sinPhi;
                p.ay = p.vy * cosPhi + p.vx * sinPhi;
                p.x += p.vx;
                p.y += p.vy;
                p.vx += p.ax;
                p.vy += p.ay;
                
                //画面外に出たら削除
                if (p.x < xMin || p.x > xMax || p.y < yMin || p.y > yMax)
                {
                    _particlesPool.push(p);
                    _particles.splice(j, 1);
                    continue;
                }
                
                bulletPoint.x = p.x - bWidth_2;
                bulletPoint.y = p.y - bHeight_2;
                _canvas.copyPixels(_bulletImg[p.ci], bulletRect, bulletPoint);
            }
            _canvas.unlock();
        }
    }
}

class Particle
{
    public var x:Number = 0;
    public var y:Number = 0;
    public var vx:Number = 0;
    public var vy:Number = 0;
    public var ax:Number = 0;
    public var ay:Number = 0;
    public var ci:int = 0;
}