我的作法如下
1.利用tilemap,定義出每條路線的起點跟終點,還有所經過的所有點
2.將每條路徑的點,利用FlxPath轉化成node
3.接著把enemy套上followPath,並把我們自訂的path丟進去,enemy就會跟著自訂的路線走啦
demo:
http://a-z.tw/blogger/assample/btdsample/BTDsample.html
主要functioin如下
class HTD_map:
package
{
import org.flixel.*;
import org.flixel.system.FlxTile;
public class HTD_map extends FlxTilemap
{
private var categoryNumber:uint;
public var paths:Array;
public function HTD_map(categoryNumber:uint)
{
super();
this.categoryNumber=categoryNumber;
}
public function findAllPathForBTD():Array
{
paths=new Array(categoryNumber);
var startPoints:Array=new Array;
var endPoints:Array=new Array;
for(var yIndex:uint=0;yIndex<heightInTiles;yIndex++)
{
for(var xIndex:uint=0;xIndex<widthInTiles;xIndex++)
{
var tile:uint=getTile(xIndex,yIndex);
if(tile<=categoryNumber&&tile!=0)//start ., get center=>+0.5
startPoints[tile-1]=new FlxPoint((xIndex+0.5)*_tileWidth,(yIndex+0.5)*_tileHeight);
else if(tile>categoryNumber*2)//start
endPoints[tile-(categoryNumber*2)-1]=new FlxPoint((xIndex+0.5)*_tileWidth,(yIndex+0.5)*_tileHeight);
}
}
var paths:Array=new Array;
for(var index:uint=0;index<startPoints.length;index++)
paths.push(findPath(startPoints[index],endPoints[index]));
return paths;
}
public override function findPath(Start:FlxPoint,End:FlxPoint,Simplify:Boolean=true,RaySimplify:Boolean=false):FlxPath
{
//figure out what tile we are starting and ending on.設立起點跟終點在map上的絕對位置 一維展開
var startIndex:uint = int((Start.y-y)/_tileHeight) * widthInTiles + int((Start.x-x)/_tileWidth);
var endIndex:uint = int((End.y-y)/_tileHeight) * widthInTiles + int((End.x-x)/_tileWidth);
//取得相對路徑的通行記號
var currectCategory:uint=getTileByIndex(startIndex)+categoryNumber;
//figure out how far each of the tiles is from the starting tile
var distances:Array = computePathDistanceOfHTD(startIndex,endIndex,currectCategory);
if(distances == null)//這裡會把所有的可能畫出來 所以畫出來的路徑其實不止一條
return null;
//then count backward to find the shortest path.//計算返回的次數找出捷徑
var points:Array = new Array();
walkPath(distances,endIndex,points);//這裡找出捷徑上的每個點依序的位置
//reset the start and end points to be exact
var node:FlxPoint;
node = points[points.length-1] as FlxPoint;
node.x = Start.x;
node.y = Start.y;
node = points[0] as FlxPoint;
node.x = End.x;
node.y = End.y;
//some simple path cleanup options
if(Simplify)
simplifyPath(points);
if(RaySimplify)
raySimplifyPath(points);
//finally load the remaining points into a new path object and return it
var path:FlxPath = new FlxPath();
var i:int = points.length - 1;
while(i >= 0)
{
node = points[i--] as FlxPoint;
if(node != null)
path.addPoint(node,true);
}
return path;//path 中的node真的是node,所以會減化點,就只有轉折處會記錄下來成node
}
protected function computePathDistanceOfHTD(StartIndex:uint, EndIndex:uint,currectCategory:uint):Array
{
//Create a distance-based representation of the tilemap.
//All walls are flagged as -2, all open areas as -1.
var mapSize:uint = widthInTiles*heightInTiles;
var distances:Array = new Array(mapSize);
var i:int = 0;
while(i < mapSize)
{
if(_data[i]==currectCategory||_data[i]==(currectCategory+categoryNumber))
distances[i] = -1;//有路設為-1
else
distances[i] = -2;//沒路設為-2
i++;
}
distances[StartIndex] = 0;//起點設為0
var distance:uint = 1;
var neighbors:Array = [StartIndex];
var current:Array;
var currentIndex:uint;
var left:Boolean;
var right:Boolean;
var up:Boolean;
var down:Boolean;
var currentLength:uint;
var foundEnd:Boolean = false;
while(neighbors.length > 0)
{
current = neighbors;
neighbors = new Array();
i = 0;
currentLength = current.length;
while(i < currentLength)
{
currentIndex = current[i++];
if(currentIndex == EndIndex)
{
foundEnd = true;
neighbors.length = 0;
break;
}
//basic map bounds
left = currentIndex%widthInTiles > 0;
right = currentIndex%widthInTiles < widthInTiles-1;
up = currentIndex/widthInTiles > 0;
down = currentIndex/widthInTiles < heightInTiles-1;
var index:uint;
if(up)
{
index = currentIndex - widthInTiles;
if(distances[index] == -1)
{
distances[index] = distance;
neighbors.push(index);
}
}
if(right)
{
index = currentIndex + 1;//如果往右 index就+1
if(distances[index] == -1)//如果右邊那格是-1代表能走
{
distances[index] = distance;//就將那一格設為1
neighbors.push(index);
}
}
if(down)
{
index = currentIndex + widthInTiles;
if(distances[index] == -1)
{
distances[index] = distance;
neighbors.push(index);
}
}
if(left)
{
index = currentIndex - 1;
if(distances[index] == -1)
{
distances[index] = distance;
neighbors.push(index);
}
}
if(up && right)
{
index = currentIndex - widthInTiles + 1;
if((distances[index] == -1))
{
distances[index] = distance;
neighbors.push(index);
}
}
if(right && down)//右下
{
index = currentIndex + widthInTiles + 1;
if((distances[index] == -1))
{//如果右下那格可以走,並且要滿足 下面跟右邊都同時能走
//在這裡 因為上面right跟down都已加入路徑,所以行走的方式會是先右在下
distances[index] = distance;
neighbors.push(index);
}
}
if(left && down)
{
index = currentIndex + widthInTiles - 1;
if((distances[index] == -1))
{
distances[index] = distance;
neighbors.push(index);
}
}
if(up && left)
{
index = currentIndex - widthInTiles - 1;
if((distances[index] == -1))
{
distances[index] = distance;
neighbors.push(index);
}
}
}
distance++;
}
if(!foundEnd)
distances = null;
return distances;
}
}
}
source code
沒有留言:
張貼留言