// 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; } } copyPixelsを使用(追記あり) - forked from: 弾幕 - パーティクルの応用で弾幕