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

forked from: forked from: forked from: パーティクルの応用で弾幕2 - 早くなったよ~

changed:
-> 効果測定用に100fpsにしました。
-> enterFrame内でのnewと定数の再計算を減らしました。
-> vectorをやめて双方向連結リストにしました。
-> http://wonderfl.net/code/dd96bd457071a86d4406a8019aa01ef0f773abf8
上記URLの挙動計算アルゴリズム改善を移植させて頂きました。
-> particlesを初期化以降はnewしなくていいように配列で準備してみましたが
こちらは目に見える効果がありませんでした。
メソッド呼び出し分のオーバヘッド+中身の処理でトントンぐらいなんでしょうか。
particlesがもっと大きい構造体になれば効果が現れるのかな?

comment:
forkの使い方を間違えました。すみません。

null参照や無限ループでブラウザを落としてしまう時間がありました。
申し訳ありません。

なんかインデントが無茶苦茶になってしまいました。
EDITフィールドから見ると正常なのですが・・・

todo:

コードのリファクタリング & 最適化

Nicolasが最適化してくれました。
http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51
BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!
めっちゃ早いよ!これ!
/**
 * Copyright koshitarou ( http://wonderfl.net/user/koshitarou )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hM9B
 */

// forked from hacker_y48qdmdh's forked from: forked from: パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieee's forked from: パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's パーティクルの応用で弾幕2 - 早くなったよ~
// forked from coppieeee's 弾幕 - パーティクルの応用で弾幕

/*
changed:
-> 効果測定用に100fpsにしました。
-> enterFrame内でのnewと定数の再計算を減らしました。
-> vectorをやめて双方向連結リストにしました。
-> http://wonderfl.net/code/dd96bd457071a86d4406a8019aa01ef0f773abf8
   上記URLの挙動計算アルゴリズム改善を移植させて頂きました。
-> particlesを初期化以降はnewしなくていいように配列で準備してみましたが
   こちらは目に見える効果がありませんでした。
   メソッド呼び出し分のオーバヘッド+中身の処理でトントンぐらいなんでしょうか。
   particlesがもっと大きい構造体になれば効果が現れるのかな?
   
comment:
forkの使い方を間違えました。すみません。

null参照や無限ループでブラウザを落としてしまう時間がありました。
申し訳ありません。

なんかインデントが無茶苦茶になってしまいました。
EDITフィールドから見ると正常なのですが・・・

todo:
*/

//コードのリファクタリング & 最適化
//
// Nicolasが最適化してくれました。
// http://wonderfl.net/code/63f88f2189846bdc7275a01d5d228b1607344e51
// BitmapData#draw() を BitmapData#coloyPixces() に変えるだけ!
// めっちゃ早いよ!これ!

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(frameRate="100",width="512",height="512" )]
    public class PShooting extends Sprite 
    {
        public static const WIDTH:Number = 512;
        public static const HEIGHT:Number = 512;
                public static const PHI:Number = Math.PI / 180 * 80;
        
                public static const PARTICLES_NUM_MAX:uint = 1280; // とりあえず1280個

        //弾のビットマップキャッシュ
        private var _bulletImg:BitmapData;
                // ビットマップ描画改善用
                private var _bulletImg_hWidth:Number;
                private var _bulletImg_hHeight:Number;

        //キャンバス
        private var _canvas:BitmapData;

        // パーティクル表示リスト
                private var _particles_head:Particle; // リンクリストの頭
                private var _particles_tail:Particle; // リンクリストの美尻
                private var _particles_num:int; // 表示中のパーティクル数
                
                // パーティクルワークリスト
                private var _particles_work_current:int;
                private var _particles_work:Vector.<Particle>; // ワーク

        //敵。というか弾の再生位置。
        private var _enemy:Particle;
                
        public function PShooting()
        {
            //Wonderfl.capture_delay( 7 );
            
            //キャンバスの生成
            _canvas = new BitmapData(WIDTH, HEIGHT,false,0x000000);
            var cb:Bitmap = new Bitmap(_canvas);
            addChild(cb);
            
                        // パーティクルリスト関連
                        _particles_head = new Particle(0,0,0,0);
                        _particles_tail = _particles_head;
                        _particles_work = new Vector.<Particle>(PARTICLES_NUM_MAX);
                        
                        // ワーク初期化
                        for( var i:uint=0; i<PARTICLES_NUM_MAX; ++i ){
                            _particles_work[i] = new Particle(0,0,0,0);
                        }
                        _particles_work_current = 0;
                        
            _enemy = new Particle(0,0,0,0);
            
            //弾のBitmapの生成
            //Shapeに円を書く。
            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            g.beginFill(0x00AAFF,0.5);
            g.drawCircle(16, 16, 16);
            g.beginFill(0x55FFFF);
            g.drawCircle(16, 16, 8);
            g.endFill();
            
            //BitmapDataにdraw()
            _bulletImg = new BitmapData(shape.width, shape.height, true, 0xFFFFFF);
            _bulletImg.draw(shape);
            
                        // パラメータ記憶
                        _bulletImg_hWidth = _bulletImg.width/2;
                        _bulletImg_hHeight = _bulletImg.height/2;

            //Statsの生成
            var stats:Stats = new Stats();
            addChild(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;
            addChild(tf);
            addEventListener(Event.ENTER_FRAME, function(e:Event):void {
                tf.text = "bullets:" + _particles_num + "\n" +
                                          "index:" + _particles_work_current;
                //tf.text += 
            });
        }
        private var _radian:Number = 0;

                private function getParticle():Particle{
                    var ret:Particle = null;
                    
                    var end_index:int = _particles_work_current;
                    var index:int     = end_index + 1;
                    var list:Vector.<Particle> = _particles_work;
                    
                    while( index != end_index ){
                        if( index >= PARTICLES_NUM_MAX ){
                            index = 0;
                        }
                        
                        var p:Particle = list[ index ];

                        if( p.is_alive == false ){
                            _particles_work_current = index;
                            ret = p;
                            break;
                        }
                        ++index;
                    }
                                        
                    return ret;
                }

        private function onEnterFrame(e:Event):void
        {
            _canvas.lock();
            var cr:Rectangle = new Rectangle(0, 0, _canvas.width, _canvas.height);
            var ct:ColorTransform = new ColorTransform (0.8, 0.8, 0.9);
            _canvas.colorTransform(cr, ct);
            
            //弾の生成場所をマウスのところへ移動
            _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) * 124.2;
            
            //一フレームあたりの弾の生成数
            var bCount:int = 10;
            var bRadian:Number = _radian;
            
            for (var i:int = 0; i <bCount; i++ )
            {
                            // newしている所とメソッド呼び出しと差し替えてもfpsにあまり差異なし。
                            // トントンといった所なのでしょうか。
                    var newP:Particle = this.getParticle();
                    //var newP:Particle = new Particle();
                            
                            if( newP ){
                                newP.x = _enemy.x;
                                newP.y = _enemy.y;
                                newP.vx = Math.cos(bRadian) * 3;
                                newP.vy = Math.sin(bRadian) * 3;
                                newP.is_alive = true;
                                newP.next = null;
                                newP.prev = _particles_tail;

                                _particles_tail.next = newP;
                                _particles_tail = newP;
                                
                                bRadian += Math.PI *2 / bCount;
                            }
            }
            
            //弾の移動
                        var bulletPoint:Point = new Point();
                        var h_width:Number = _bulletImg_hWidth;
                        var h_height:Number = _bulletImg_hHeight;
                        var list_tail:Particle = null;
                        var p_num:int = 0;
                        
                        // ベクトル(二次元マトリクス)回転で計算
                        var phi:Number = PHI;
                        var cosPhi:Number = Math.cos(phi) * 0.02; //0.02はオマケ
                        var sinPhi:Number = Math.sin(phi) * 0.02;
                        
                        for(var p:Particle = _particles_head.next; p!=null; p=p.next )
            {
                            //ベクトルうめぇ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 < 0 || p.x > WIDTH || p.y < 0 || p.y > HEIGHT)
                            { 
                                var prev:Particle = p.prev;
                                
                                // 前→次
                                prev.next = p.next;
                                    
                                // 前←次
                                if( p.next ){
                                    p.next.prev = prev;
                                }
                                
                                // 無効化
                                p.is_alive = false;
                                p.next = null;
                                p.prev = null;
                                
                                p = prev;
                } else {
                                ++p_num; // 有効な弾数として加算
                                    
                                //弾の描画。一番のボトルネック!(どうしようもないがな)
                        //_canvas.draw(_bulletImg,matrix);

                //最適化!
                //draw()じゃなくてcopyPixels()使った方がめっちゃ早いよ!!
                //早くなったがボトルネックであることは変わらない。
                                bulletPoint.x = p.x - h_width;
                                bulletPoint.y = p.y - h_height;        
                              
                _canvas.copyPixels(_bulletImg, _bulletImg.rect, bulletPoint);
                            }
                            
                            list_tail = p;
            }

                        _particles_tail = list_tail;
            _particles_num = p_num;

             _canvas.unlock();
        }
    }
}
class Particle
{
    public var x:Number;
    public var y:Number;
    public var vx:Number;
    public var vy:Number;
    public var ax:Number = 0;
    public var ay:Number = 0;

        public var prev:Particle = null;
        public var next:Particle = null;
        
        public var is_alive:Boolean = false;
    
    public function Particle(x:Number = 0, y:Number = 0, vx:Number = 0, vy:Number = 0)
    {
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
    }
}