浏览代码

added PathFind

ncannasse 11 年之前
父节点
当前提交
0d4d3aafe3
共有 2 个文件被更改,包括 129 次插入0 次删除
  1. 21 0
      hxd/impl/FastIO.hx
  2. 108 0
      hxd/impl/PathFind.hx

+ 21 - 0
hxd/impl/FastIO.hx

@@ -102,4 +102,25 @@ class FastIntIO extends FastIO<Int> {
 		}
 	}
 
+	public inline function rec2dk( x, y, bits, callb ) {
+		var k = 0;
+		add2d(x, y, bits);
+		while( true ) {
+			flush((write < read ? write : (write - read)) * 4);
+			if( !hasNext() )
+				break;
+			for( id in this ) {
+				var x = id & ((1 << bits) - 1);
+				var y = id >>> bits;
+				if( !callb(x,y,k) )
+					continue;
+				add2d(x + 1, y, bits);
+				add2d(x - 1, y, bits);
+				add2d(x, y + 1, bits);
+				add2d(x, y - 1, bits);
+			}
+			k++;
+		}
+	}
+
 }

+ 108 - 0
hxd/impl/PathFind.hx

@@ -0,0 +1,108 @@
+package hxd.impl;
+
+class PathFind {
+
+	// 0 - unreachable
+	// positive - dist+1 to reach
+	// negative - -(dist+1) : collides but reachable
+
+	var t : haxe.ds.Vector<Int>;
+	var bits : Int;
+	var init : Bool;
+	var width : Int;
+	var height : Int;
+
+	public function new(width, height) {
+		this.width = width;
+		this.height = height;
+		t = new haxe.ds.Vector<Int>(width * height);
+		bits = 0;
+		while( width >= 1 << bits )
+			bits++;
+	}
+
+	public function clear() {
+		for( i in 0...width * height )
+			t[i] = 0;
+	}
+
+	public inline function build( x : Int, y : Int, collide : Int -> Int -> Bool ) {
+		var tmp = new FastIO.FastIntIO();
+		tmp.rec2dk(x, y, bits, function(x, y, k) {
+			if( x < 0 || y < 0 || x >= width || y >= height ) return false;
+			k++;
+			var a = x + y * width;
+			var p = t[a];
+			if( p != 0 && Math.iabs(p) <= k ) return false;
+			if( collide(x, y) ) {
+				t[a] = -k;
+				return k == 1;
+			}
+			t[a] = k;
+			return true;
+		});
+	}
+
+	public function getPath( x : Int, y : Int ) {
+		var a = x + y * width;
+		var k = Math.iabs(t[a]);
+		if( k == 0 ) return null;
+		var path = [];
+		while( k > 1 ) {
+			k--;
+			if( x > 0 && t[a - 1] == k ) {
+				x--;
+				a--;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( y > 0 && t[a - width] == k ) {
+				y--;
+				a-=width;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( x < width-1 && t[a + 1] == k ) {
+				x++;
+				a++;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( y < height - 1 && t[a + width] == k ) {
+				y++;
+				a+=width;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			// target collides
+			if( k != 1 ) throw "assert "+k;
+			k = -1;
+			if( x > 0 && t[a - 1] == k ) {
+				x--;
+				a--;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( y > 0 && t[a - width] == k ) {
+				y--;
+				a-=width;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( x < width-1 && t[a + 1] == k ) {
+				x++;
+				a++;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+			if( y < height - 1 && t[a + width] == k ) {
+				y++;
+				a+=width;				path.push( { x:x, y:y } );
+				continue;
+			}
+			throw "assert";
+		}
+		return path;
+	}
+
+}