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: 直線描画高速化テスト

Get Adobe Flash player
by tail_y 11 Jun 2009
/**
 * Copyright tail_y ( http://wonderfl.net/user/tail_y )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/pCWa
 */

// forked from tail_y's 直線描画高速化テスト
package {
 
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.utils.getTimer;

	public class DrawLineTest extends Sprite
	{
		/*
		 マリモのための、直線描画高速化テスト。 
		 Flashの線描画は重いって有名だから、オリジナルの手法で勝つる!って思って頑張ったけど
		 微妙な結果に・・・orz
		 setPixel使えば軽く(約0.7倍)なるんだけど、その場合太さが表現できない。
		 あと、なんかマイナス方向への描画が汚い。
		 誰かアイデアをください。
		 
		 アンチエイリアスはひとまず無視して、2px以上の線を高速に描画できればとりあえず成功。マリモに応用できるはず。

		 一応、僕の環境では45%くらい高速化しているんだけど、どうかな。
                */
		
		public static const TEST_LINE_NUM:uint = 10000;	// テストする回数
		public static const DISPLAY_LINE_NUM:uint = 100;	// 見た目も確認したいから表示用に、少ない回数の描画もするよ~。
		
		public static const BITMAP_SIZE:uint = 232;	// 描画サイズ
		public static const BITMAP_CENTER:uint = BITMAP_SIZE/2;	// 描画の中央
		public static const LINE_LENGTH:uint = 100;	// 線の長さ
		public static const LINE_COLOR:uint = 0x33aa22;
		
		public static const LINE_THICNESS:Number = 2;
		
		public function DrawLineTest()
		{
			addEventListener(Event.ADDED_TO_STAGE, init);	// flexBuilderとの互換性。
		}

		private function init(e:Event):void {
			// SWF設定
			stage.frameRate = 24
			stage.quality = StageQuality.LOW;
			
			// 変数
			var timeCount0:Number, timeCount1:Number;	// 時間計測用
			var xList:Array, yList:Array;	// sinとcosをあらかじめ計算しておくリスト
			var infoDisplay:TextField = new TextField();	// 時間表示TF
			
			// 計測をなるべく純粋にするために、座標位置は計算しておく。
			xList = calcXList(TEST_LINE_NUM);
			yList = calcYList(TEST_LINE_NUM);
			
			// 通常の描画をするよ。
			timeCount0 = getTimer();
			drawLine_normal(TEST_LINE_NUM, xList, yList);
			timeCount1 = getTimer();
			infoDisplay.appendText("normal:" + (timeCount1 - timeCount0) + "\n");
			
			// fillRectによる描画をするよ。
			timeCount0 = getTimer();
			drawLine_rect(TEST_LINE_NUM, xList, yList);
			timeCount1 = getTimer();
			infoDisplay.appendText("rect:" + (timeCount1 - timeCount0) + "\n");
			
			// 表示用の描画をするよ(時間は計らない)
			xList = calcXList(DISPLAY_LINE_NUM);
			yList = calcYList(DISPLAY_LINE_NUM);
			var normalBitmapData:BitmapData = drawLine_normal(DISPLAY_LINE_NUM, xList, yList);
			var rectBitmapData:BitmapData = drawLine_rect(DISPLAY_LINE_NUM, xList, yList);
			
			// まとめて表示
			var normalBitmap:Bitmap = new Bitmap(normalBitmapData);
			var rectBitmap:Bitmap = new Bitmap(rectBitmapData);
			normalBitmap.x = 0;
			normalBitmap.y = 0;
			rectBitmap.x = BITMAP_SIZE;
			rectBitmap.y = 0;
			addChild(normalBitmap);
			addChild(rectBitmap);
			addChild(infoDisplay);
			
			// 縮小表示もしておく。
			stage.quality = StageQuality.HIGH;
			
			var normalBitmapSmall:Bitmap = new Bitmap();
			var rectBitmapSmall:Bitmap = new Bitmap();
			normalBitmapSmall.bitmapData = new BitmapData(BITMAP_SIZE/2, BITMAP_SIZE/2, false);
			rectBitmapSmall.bitmapData = new BitmapData(BITMAP_SIZE/2, BITMAP_SIZE/2, false);
			var smallMatrix:Matrix = new Matrix();
			smallMatrix.scale(0.5, 0.5);
			normalBitmapSmall.bitmapData.draw(normalBitmapData, smallMatrix, null, null, null, true);
			rectBitmapSmall.bitmapData.draw(rectBitmapData, smallMatrix, null, null, null, true);
			normalBitmapSmall.x = 0;
			normalBitmapSmall.y = BITMAP_SIZE
			rectBitmapSmall.x = BITMAP_SIZE;
			rectBitmapSmall.y = BITMAP_SIZE;
			addChild(normalBitmapSmall);
			addChild(rectBitmapSmall);
		}
		
		// Graphicを使った描画をする。
		private function drawLine_normal(num:int, xList:Array, yList:Array):BitmapData{
			var sprite:Sprite = new Sprite();
			var graphics:Graphics = sprite.graphics;
			var i:int
			
			graphics.lineStyle(LINE_THICNESS, LINE_COLOR, 1);
			for (i = 0; i < num; i++){
				graphics.moveTo(BITMAP_CENTER, BITMAP_CENTER);
				graphics.lineTo(xList[i], yList[i]);
			}
			var bitmapData:BitmapData = new BitmapData(BITMAP_SIZE, BITMAP_SIZE, false, 0xffffff);
			bitmapData.draw(sprite);
			return bitmapData;
		}
		
		// BitmapへのfillRectを使った描画をする
		private function drawLine_rect(num:int, xList:Array, yList:Array):BitmapData{
			var bitmapData:BitmapData = new BitmapData(BITMAP_SIZE, BITMAP_SIZE, false, 0xffffff);
			var rectNum:int;
			var rect:Rectangle = new Rectangle(0, 0, LINE_THICNESS, LINE_THICNESS);		// 予め作って使いまわす。
			var i:int, j:int;
			var stepX:Number, stepY:Number;
			
			for (i = 0; i < num; i++){
				rectNum = Math.max(Math.abs(xList[i] - BITMAP_CENTER), Math.abs(yList[i] - BITMAP_CENTER));	// 多いほうの座標の数だけ四角が必要。
				stepX = (xList[i] - BITMAP_CENTER) / rectNum;
				stepY = (yList[i] - BITMAP_CENTER) / rectNum;
				for (j = 0; j < rectNum; j++){
					rect.x = BITMAP_CENTER + j*stepX;
					rect.y = BITMAP_CENTER + j*stepY;
					bitmapData.fillRect(rect, LINE_COLOR)
					/* 上の3行の処理を、↓1行にすると、Flashの描画より軽くなるんだけど、太さに対応できない・・・。
					bitmapData.setPixel(int(BITMAP_CENTER + j*stepX), int(BITMAP_CENTER + j*stepY), LINE_COLOR);
					*/
				}
			}
			return bitmapData;
		}
		
		private function calcXList(num:int):Array{
			var ans:Array = [];
			for (var i:int = 0; i < num; i++){
				ans.push(BITMAP_CENTER + Math.cos(i * 2 * Math.PI / num) * LINE_LENGTH);
			}
			return ans;
		}
		private function calcYList(num:int):Array{
			var ans:Array = [];
			for (var i:int = 0; i < num; i++){
				ans.push(BITMAP_CENTER + Math.sin(i * 2 * Math.PI / num) * LINE_LENGTH);
			}
			return ans;
		}
	}
}