forked from: DotLight [Red]
forked from DotLight [Red] (diff: 302)
Sprite と線の接点を調べるためのテストプログラムです。 * 手っ取り早くブレゼンハムアルゴリズムを使いたかったので * fork させてもらいました。 2010/08/20 Zier
ActionScript3 source code
/**
* Copyright zier ( http://wonderfl.net/user/zier )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/y9t0
*/
// forked from ProjectNya's DotLight [Red]
/*
* Sprite と線の接点を調べるためのテストプログラムです。
* 手っ取り早くブレゼンハムアルゴリズムを使いたかったので
* fork させてもらいました。 2010/08/20 Zier
*/
package {
import flash.events.MouseEvent
import flash.display.Sprite;
import flash.geom.Point;
[SWF(backgroundColor="#000000", width="465", height="465", frameRate="30")]
public class Main extends Sprite {
private var block: Sprite;
private var testLayer: Sprite;
public function Main() {
block = new Sprite();
block.graphics.beginFill(0x808080)
block.graphics.drawRect(-50, -20, 100, 40)
block.graphics.endFill()
block.x = 230
block.y = 230
block.rotation = 30
addChild(block)
testLayer = new Sprite();
addChild(testLayer);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown)
}
private function onMouseDown(e: MouseEvent): void {
var x0: int = e.stageX
var y0: int = e.stageY
var x1: int = block.x
var y1: int = block.y
var p: Point = null
Bresenham.line(x0, y0, x1, y1, function(x: int, y: int, a: Boolean): Boolean {
if (a == block.hitTestPoint(x, y, true)) {
p = new Point(x, y)
return true;
}
return false;
});
testLayer.graphics.clear()
testLayer.graphics.lineStyle(2, 0xff0000);
testLayer.graphics.moveTo(x0, y0);
testLayer.graphics.lineTo(p.x, p.y);
testLayer.graphics.drawEllipse(p.x - 5, p.y - 5, 10, 10);
}
}
}
class Bresenham {
// 各処理では f() に引き渡した関数を呼ぶ形
public static function line(x0:int, y0:int, x1:int, y1:int, f: Function):void {
var steep:Boolean = Math.abs(y1 - y0) > Math.abs(x1 - x0);
var t:int;
if (steep) {
t = x0;
x0 = y0;
y0 = t;
t = x1;
x1 = y1;
y1 = t;
}
// 途中で走査を中断するためのフラグを追加
var aboutFlag: Boolean = true;
if (x0 > x1) {
t = x0;
x0 = x1;
x1 = t;
t = y0;
y0 = y1;
y1 = t;
// 指定した二点の位置関係によっては走査を逆転し最適化を行っているのですね
// なので、開始と終了を意識しない場合の走査自体は効率的。
// ただ、開始から終了を明確に意識する処理が行いたい場合にはロジック外で考慮が必要となる。
// 今回、aboutFlag を反転して f() に引き渡して対応したが、方向を意識する処理ならば
// 素直に開始から終了を走査するコードを書いた方が良いか?
aboutFlag = false;
}
var dx:int = x1 - x0;
var dy:int = Math.abs(y1 - y0);
var e:int = dx*0.5;
var ys:int = (y0 < y1) ? 1 : -1;
var y:int = y0;
for (var x:int = x0; x <= x1; x++) {
if (steep) {
if (f(y, x, aboutFlag)) return;
} else {
if (f(x, y, aboutFlag)) return;
}
e = e - dy;
if (e < 0) {
y = y + ys;
e = e + dx;
}
}
}
}