addChildとcopyPixels

画面上に大量弾を表示させて動かす場合、addChildとBitmapData.copyPixelsを使うのではどのくらい実行速度が違うのかを試してみました。


こちら

下の数字が現在画面上に存在する弾の数で、スライダーを動かすと弾の量を変更できます。


ソース

package
{
	import com.bit101.components.*;
	
	import flash.display.*;
	import flash.events.*;
	import flash.filters.GlowFilter;
	import flash.geom.*;
	import flash.text.TextField;

	[SWF(backgroundColor=0, frameRate=60, width=500, height=700)]
	public class CopyPixelsTest extends Sprite
	{
		
		private var nt:TextField = new TextField();
		private var list:Vector.<A>;
		private var list2:Vector.<B>;
		private var angle:Number = 0;
		private var n:int = 50;
		private var bmpData:BitmapData;
		private var view:Bitmap, viewData:BitmapData;
		private var rect:Rectangle;
		private var bw_2:int, bh_2:int, w:int=500, h:int=500, w_2:int=250, h_2:int=250;
		private var point:Point = new Point();
		private var slider:HSlider;
		
		public function CopyPixelsTest()
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			list = new Vector.<A>;
			list2 = new Vector.<B>;
			viewData = new BitmapData(w,h, false, 0);
			view = new Bitmap(viewData);
			
			normal();
			
			new PushButton(this, 300, 600, "addChild", normal);
			new PushButton(this, 300, 630, "copyPixels", copy);
			slider = new HSlider(this, 300, 660, slide);
			slider.maximum = 200;
			slider.minimum = 10;
			slider.value = 50;
			addChild(nt);
			
			nt.y = 550;
			nt.x = 150;
			nt.textColor = 0xFFFFFF;
			addChild(new Stats()).y = 550;
		}
		
		private function slide(e:Event):void{
			n = int(slider.value);
		}
		
		private function normal(e:MouseEvent=null):void{
			resetCopy();
			addEventListener(Event.ENTER_FRAME, onFrame1);
		}
		
		private function resetCopy():void{
			removeEventListener(Event.ENTER_FRAME, onFrame2);
			viewData.fillRect(viewData.rect, 0);
			//removeChild(view);
			list2 = new Vector.<B>;
		}
		
		private function onFrame1(e:Event):void{
			nt.text = list.length.toString();
			for(var i:int = 0; i < n; i++){
				var a:A = new A();
				a.vx = Math.cos(angle)*5;
				a.vy = Math.sin(angle)*5;
				a.x = w_2;
				a.y = h_2;
				addChild(a);
				list.push(a);
				angle += 0.015;
			}
			i = list.length;
			while(i--){
				a = list[i];
				a.x += a.vx;
				a.y += a.vy;
				if(a.x < 0 || a.y < 0 || w < a.x || h < a.y){
					removeChild(a);
					list.splice(i,1);
					a = null;
				}
			}
		}
		
		
		private function copy(e:MouseEvent):void{
			resetNormal();
			addChild(view);
			
			var m:Matrix = new Matrix();
			m.createGradientBox(20,20,0,-10,-10);
			var sp:Sprite = new Sprite();
			sp.graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFF0000], [1.0,1.0], [0, 255], m);
			sp.graphics.drawCircle(0,0,10);
			sp.graphics.endFill();
			bmpData = new BitmapData(sp.width, sp.height, true, 0xFFFFFF);
			bmpData.draw(sp, new Matrix(1, 0, 0, 1, sp.width/2, sp.height/2));
			rect = bmpData.rect;
			bw_2 = bmpData.width/2;
			bh_2 = bmpData.height/2;
			
			addEventListener(Event.ENTER_FRAME, onFrame2);
		}
		
		private function resetNormal():void{
			removeEventListener(Event.ENTER_FRAME, onFrame1);
			for(var i:int = 0; i < list.length; i++){
				removeChild(list[i]);
			}
			list = new Vector.<A>();
		}
		
		private function onFrame2(e:Event):void{
			nt.text = list2.length.toString();
			viewData.lock();
			viewData.colorTransform(viewData.rect, new ColorTransform(0.8, 0.8, 0.8));
			for(var i:int = 0; i < n; i++){
				var a:B = new B();
				a.vx = Math.cos(angle)*5;
				a.vy = Math.sin(angle)*5;
				a.x = w_2;
				a.y = h_2;
				list2.push(a);
				angle += 0.015;
			}
			i = list2.length;
			while(i--){
				a = list2[i];
				a.x += a.vx;
				a.y += a.vy;
				if(a.x < 0 || a.y < 0 || w < a.x || h < a.y){
					list2.splice(i,1);
					a = null;
					continue;
				}
				
				point.x = a.x-bw_2;
				point.y = a.y-bh_2;
				viewData.copyPixels(bmpData, rect, point);
			}
			viewData.unlock();
		}
	}
}
import flash.display.*;
import flash.filters.GlowFilter;
import flash.geom.Matrix;

class A extends Shape{
	public var vx:Number, vy:Number;
	public function A():void{
		var m:Matrix = new Matrix();
		m.createGradientBox(20,20,0,-10,-10);
		graphics.beginGradientFill(GradientType.RADIAL, [0xFFFFFF, 0xFF0000], [1.0,1.0], [0, 255], m);
		graphics.drawCircle(0,0,10);
		graphics.endFill();
	}
}

class B{
	public var x:Number, y:Number, vx:Number, vy:Number;
}