[AS3] 直線で閉じた図形を描く [Edit]

Graphicsクラスの描画メソッドを使うと、Spriteなどのインスタンスに直線が引けます。そこで、頂点座標にしたがって多角形などの閉じた図形が描ける関数を定義してみましょう(図001)。さほど難しいスクリプトではありません。けれど、あえてややこしく書いてしまうことも少なくないようです。そうならないためのちょっとしたコツをご紹介します。

図001■閉じた図形を描く
FF1101201_001.gif

MovieClipやSpriteインスタンスに描画するためには、まずそのターゲットとなるGraphicsオブジェクトをSprite.graphicsプロパティから取出します。つぎに、参照したGraphicsオブジェクトに対して、Graphicsクラスの描画メソッドを用いて線描します。

線の始まりはGraphics.moveTo()、終わりはGraphics.lineTo()メソッドで定めます。線の引き終わりは、つぎの引き始めの位置になりますので、連続した線を描くときはGraphics.moveTo()メソッドは、初めに1度呼出せば足ります。線の太さやカラーなどのスタイルは、Graphics.lineStyle()メソッドで設定します。

閉じた図形を描く関数drawLines()は、つぎのような仕様にしましょう。図形の頂点座標はPointインスタンスとし、配列に納めて第1引数に渡します。第2引数は、描画対象のSpriteインスタンスです。

function drawLines(_points:Array, targetSprite:Sprite):void

配列の最初の座標から線を引き始め、最後の座標まで線描したうえで、初めの座標に戻って図形を閉じます。この手順をそのままスクリプトにしようとすると、ついつぎのフレームアクションのような関数になりがちです。

スクリプト001■線描の手順をそのままスクリプトにした例
// フレームアクション
var canvas:Sprite = new Sprite();
var points:Array = [];
points.push(new Point(0, 0));
points.push(new Point(100, 0));
points.push(new Point(100, 100));
points.push(new Point(0, 100));
addChild(canvas);
canvas.x = 10;
canvas.y = 10;
drawLines(points, canvas);
// 閉じた多角形を描く関数定義
function drawLines(_points:Array, targetSprite:Sprite):void {
	var nLength:uint = _points.length;
	var myGraphics:Graphics = targetSprite.graphics;
	myGraphics.lineStyle(2, 0x0000FF);
	for (var i:uint = 0; i <= nLength; i++) {
		var _point:Point = _points[i % nLength];  // i = nLengthのとき0に戻す
		if (i == 0) {  // 開始座標のとき
			myGraphics.moveTo(_point.x, _point.y);
		} else {
			myGraphics.lineTo(_point.x, _point.y);
		}
	}
}

[ムービープレビュー]を確かめると、前掲図001のような正方形が描かれます。とくに不具合はありません。しかし、関数(drawLines())の処理に無駄が多いといえます。閉じた図形なのですから、第1引数の配列(_point)の最初の座標から描き始める必要はないのです。そこに気づくと、関数はもっとすっきり定義できます。

スクリプト002■描線を最後の座標から始めるように修正した関数
// 閉じた多角形を描く関数定義
function drawLines(_points:Array, targetSprite:Sprite):void {
	var nLength:uint = _points.length;
	var _point:Point = _points[nLength - 1];  // 配列の最後の座標
	var myGraphics:Graphics = targetSprite.graphics;
	myGraphics.lineStyle(2, 0x0000FF);
	myGraphics.moveTo(_point.x, _point.y);  // 最後の座標から描画開始
	for (var i:uint = 0; i < nLength; i++) {
		_point = _points[i];
		myGraphics.lineTo(_point.x, _point.y);
	}
}

第1引数の配列の最後の座標を、描画の開始位置に変えました。すると、forループ内は配列の初めの座標から終わりまで、ただ順に線描するだけです。初めの座標に戻らなくて済み、if条件もなくなりました。

コメント

この記事にコメントを書く

記事に対するテクニカルな質問はご遠慮ください(利用規約)。

その他の記事