copyPixel() vs draw()

by tananuka13
draw→copyPixelsに変えてみました。
僕の環境では120fpsくらいで違いがでました。気のせいかもしれない

追記
弾を増やし,赤いテキストフィールドをクリックすれば描画メソッドを切り替えられるようにしました!
テキストフィールド内の文字列は現在のメソッドを表しています。
♥0 | Line 157 | Modified 2010-12-25 03:13:38 | MIT License
play

ActionScript3 source code

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

// forked from sagaraKUN1's forked from: copyPixelsを使用(追記あり) - forked from: 弾幕 - パーティクルの応用で弾幕
// forked from Nicolas's copyPixelsを使用(追記あり) - forked from: 弾幕 - パーティクルの応用で弾幕
// forked from coppieeee's 弾幕 - パーティクルの応用で弾幕

/*
draw→copyPixelsに変えてみました。
僕の環境では120fpsくらいで違いがでました。気のせいかもしれない
*/

//追記
//弾を増やし,赤いテキストフィールドをクリックすれば描画メソッドを切り替えられるようにしました!
//テキストフィールド内の文字列は現在のメソッドを表しています。


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.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
        import flash.geom.Point;
    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 
    {
        public static const WIDTH:Number = 512;
        public static const HEIGHT:Number = 512;
        
        //弾のビットマップキャッシュ
        private var _bulletImg:Bitmap;
        //キャンバス
        private var _canvas:BitmapData;
        //パーティクルリスト
        private var _particles:Vector.<Particle>;
        //敵。というか弾の再生位置。
        private var _enemy:Particle;
        
        public var bulletBD:BitmapData;

                public var drawMode:String = "copyPixels";

        public function PShooting()
        {
            Wonderfl.capture_delay( 6 );
            
            //キャンバスの生成
            _canvas = new BitmapData(WIDTH, HEIGHT,false,0x000000);
            var cb:Bitmap = new Bitmap(_canvas);
            addChild(cb);
            
            _particles = new Vector.<Particle>();
            _enemy = new Particle(0,0,0,0);
            
            //弾のBitmapの生成
            //Shapeに円を書く。
            var shape:Shape = new Shape();
            var g:Graphics = shape.graphics;
            g.beginFill(0x00FFFF,0.5);
            g.drawCircle(16, 16, 16);
            g.beginFill(0x99FFFF);
            g.drawCircle(16, 16, 8);
            g.endFill();
            //BitmapDataにdraw()
            var data:BitmapData = new BitmapData(shape.width, shape.height, true, 0xFFFFFF);
            data.draw(shape);
                        bulletBD = data;

            //Bitmap生成
            _bulletImg = new Bitmap(data);
            //中心を(0,0)に置く。
            _bulletImg.x = _bulletImg.width / 2;
            _bulletImg.y = _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.length;
            });

                        //現在の描画方法
                        var tf2:TextField = new TextField();
                        tf2.y = 120;
                        tf2.textColor = 0xFFFFFF;
                        tf2.background = true;
                        tf2.backgroundColor = 0xFF0000;
                        tf2.autoSize = TextFieldAutoSize.LEFT;
                        addChild(tf2);
                        tf2.text = drawMode;
                        addEventListener(MouseEvent.CLICK, onClick);

                        function onClick(e:MouseEvent):void{
                            if(drawMode=="copyPixels"){
                                drawMode = "draw";
                            }else{
                                drawMode = "copyPixels";
                            }
                            tf2.text = drawMode;  
                        }
                }
        private var _radius:Number = 0;

        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;
            
            //弾の生成
            for (var i:int = 0; i < 10; i++ )
            {
                _radius += (Math.PI * 2 / 180) * 11.1;
                var vx:Number = Math.cos(_radius) * 3;
                var vy:Number = Math.sin(_radius) * 3;
                var newP:Particle = new Particle(_enemy.x, _enemy.y, vx, vy);
                _particles.push(newP);
            }
            
            var removedParticles:Vector.<Particle> = new Vector.<Particle>();
            
            //弾の移動
            for each(var p:Particle in _particles)
            {
                p.x += p.vx;
                p.y += p.vy;
                p.vx += p.ax;
                p.vy += p.ay;
                p.time ++;
                
                //画面外に出たらremovedParticlesに登録
                if (p.x < 0 || p.x > WIDTH || p.y < 0 || p.y > HEIGHT)
                {
                    removedParticles.push(p);
                    continue;
                }
                else if (p.time > 30)
                {
                    //弾の角度変更
                    p.time = 0;
                    var radius:Number = Math.atan2(p.vy, p.vx);
                    var speed:Number = Math.sqrt(p.vx * p.vx + p.vy * p.vy );
                    p.ax = Math.cos(radius + Math.PI / 2) * 0.08;
                    p.ay = Math.sin(radius + Math.PI / 2) * 0.08;
                }
                var matrix:Matrix = new Matrix();
                matrix.tx = p.x - _bulletImg.width/2;
                matrix.ty = p.y - _bulletImg.height / 2;
                //弾の描画。一番のボトルネック!(どうしようもないがな)
                                if(drawMode=="draw"){
                                    //drawを使用
                    _canvas.draw(_bulletImg,matrix);
                                }else{
                                //copyPixelsを使用
                                _canvas.copyPixels(bulletBD, bulletBD.rect, new Point(p.x-16, p.y-16));
                                }
            }
            
            //いらない弾を_particlesから消す。
            for each(var removedP:Particle in removedParticles)
            {
                var index:int = _particles.indexOf(removedP);
                if (index != -1)
                {
                    _particles.splice(index, 1);
                }
            }
            _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 time:Number = 0;
    public function Particle(x:Number,y:Number,vx:Number,vy:Number)
    {
        this.x = x ;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
    }
}