forked from: 直線描画高速化テスト
/**
* 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;
}
}
}