📄 astardouble.java
字号:
// Correct the position
if (x+SPRITE_SIZE<mapWidth) {
if (isNotBlock(x+SPRITE_SIZE,y)) {
if (SHOW_DEBUG)
System.out.print("change x+");
pointGoal.x += SPRITE_SIZE;
return true;
}
}
if ((x+SPRITE_SIZE<mapWidth) && (y+SPRITE_SIZE<mapHeight)) {
if (isNotBlock(x+SPRITE_SIZE,y+SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change x+ y+");
pointGoal.x += SPRITE_SIZE;
pointGoal.y += SPRITE_SIZE;
return true;
}
}
if (y+SPRITE_SIZE<mapHeight) {
if (isNotBlock(x,y+SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change y+");
pointGoal.y += SPRITE_SIZE;
return true;
}
}
if ((x>SPRITE_SIZE) && (y+SPRITE_SIZE<mapHeight)) {
if (isNotBlock(x-SPRITE_SIZE,y+SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change x- y+");
pointGoal.x -= SPRITE_SIZE;
pointGoal.y += SPRITE_SIZE;
return true;
}
}
if (x>SPRITE_SIZE) {
if (isNotBlock(x-SPRITE_SIZE,y)) {
if (SHOW_DEBUG)
System.out.print("change x-");
pointGoal.x -= SPRITE_SIZE;
return true;
}
}
if ((x>SPRITE_SIZE) && (y>SPRITE_SIZE)) {
if (isNotBlock(x-SPRITE_SIZE,y-SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change x- y-");
pointGoal.x -= SPRITE_SIZE;
pointGoal.y -= SPRITE_SIZE;
return true;
}
}
if (y>SPRITE_SIZE) {
if (isNotBlock(x,y-SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change y-");
pointGoal.y -= SPRITE_SIZE;
return true;
}
}
if ((x+SPRITE_SIZE<mapWidth) && (y>SPRITE_SIZE)) {
if (isNotBlock(x+SPRITE_SIZE,y-SPRITE_SIZE)) {
if (SHOW_DEBUG)
System.out.print("change x+ y-");
pointGoal.x += SPRITE_SIZE;
pointGoal.y -= SPRITE_SIZE;
return true;
}
}
return false;
}
/*------------------------------------------------------------------------------------*/
/**
* test if a point (in CELL units) is a valid start,
* and correct the position regarding the sprite size
*
* @param pointGoal the point (in CELL units)
* @return true if point is valid (not blocked) in the {@link #mask mask}
*/
static public boolean isValidStart(Point pointGoal) {
return aStar.isValid(pointGoal);
}
/**
* test if a point (in pixels coordinate) is a valid start.
* If it's an invalid point, search a valid point near it,
* and correct the position regarding the sprite size
*
* @param pointGoal the point
* @return true if point is valid or has been corrected, false otherwise
*/
private boolean isValid(Point pointGoal) {
// We search up to 3 pixels around the original point
int radius = 3;
int x = pointGoal.x/tileSize;
int y = pointGoal.y/tileSize;
if (isNotBlock(x,y)) {
//if (SHOW_DEBUG)
// System.out.println("valid point");
return true;
} else {
//if (SHOW_DEBUG)
// System.out.println("not a valid point -> search a valid point");
Debug.signal( Debug.NOTICE, null, "not a valid start point -> search a valid point");
//Debug.signal( Debug.NOTICE, null, " x = " + x + " , y = " + y);
}
// test if player is near border
if (x+SPRITE_SIZE>mapWidth) {
if (SHOW_DEBUG)
System.out.println("test x near border");
if (map[x-SPRITE_SIZE-1][y]) {
if (SHOW_DEBUG)
System.out.print("player near border -> change x=mapWidth-SPRITE_SIZE-1");
pointGoal.x = mapWidth-SPRITE_SIZE-1;
return true;
}
}
if (y+SPRITE_SIZE>mapHeight) {
if (SHOW_DEBUG)
System.out.println("test y near border");
if (map[x][mapHeight-SPRITE_SIZE-1]) {
if (SHOW_DEBUG)
System.out.print("player near border -> change y=mapHeight-SPRITE_SIZE-1");
pointGoal.y = mapHeight-SPRITE_SIZE-1;
return true;
}
}
// We search a valid point around the original point
//pointGoal.y = y-1;
if (isNotBlock(x,y-1)) {pointGoal.y-=tileSize;return true;}
//pointGoal.y = y+1;
if (isNotBlock(x,y+1)) {pointGoal.y+=tileSize;return true;}
//pointGoal.x = x-1;
//pointGoal.y = y-1;
if (isNotBlock(x-1,y-1)) {pointGoal.x-=tileSize;pointGoal.y-=tileSize;return true;}
//pointGoal.y = y+1;
if (isNotBlock(x-1,y+1)) {pointGoal.x-=tileSize;pointGoal.y+=tileSize;return true;}
//pointGoal.x = x+1;
//pointGoal.y = y-1;
if (isNotBlock(x+1,y-1)) {pointGoal.x+=tileSize;pointGoal.y-=tileSize;return true;}
//pointGoal.y = y+1;
if (isNotBlock(x+1,y+1)) {pointGoal.x+=tileSize;pointGoal.y+=tileSize;return true;}
//pointGoal.x = x-2;
//for (pointGoal.y=y-2;pointGoal.y<y+3;y++) {
for (int step=-2;step<3;step++) {
if (isNotBlock(x-2,y+step)) {
pointGoal.x-=2*tileSize;
pointGoal.y+=step*tileSize;
return true;
}
}
//for (pointGoal.x=x-1;pointGoal.x<x+2;x++) {
for (int step=-1;step<2;step++) {
//pointGoal.y=y-2;
if (isNotBlock(x+step,y-2)) {
pointGoal.x+=step*tileSize;
pointGoal.y-=2*tileSize;
return true;
}
//pointGoal.y=y+2;
if (isNotBlock(x+step,y+2)) {
pointGoal.x+=step*tileSize;
pointGoal.y+=2*tileSize;
return true;
}
}
//pointGoal.x = x+2;
//for (pointGoal.y=y-2;pointGoal.y<y+3;y++) {
for (int step=-2;step<3;step++) {
if (isNotBlock(x+2,y+step)) {
pointGoal.x+=2*tileSize;
pointGoal.y+=step*tileSize;
return true;
}
}
return false;
}
/*------------------------------------------------------------------------------------*/
/**
* Generates all the not blocked children of a Node
*
* @param p Node.point
* returns a Vector of child Points of the point "p"
*/
private List generateChildren(Point p) {
List listChildren = new List(8);
int x = p.x;
int y = p.y;
if (isNotBlock(x,y-1)) {listChildren.addElement(new Point(x,y-1));}
if (isNotBlock(x+1,y)) {listChildren.addElement(new Point(x+1,y));}
if (isNotBlock(x,y+1)) {listChildren.addElement(new Point(x,y+1));}
if (isNotBlock(x-1,y)) {listChildren.addElement(new Point(x-1,y));}
if (isNotBlock(x-1,y-1)) {listChildren.addElement(new Point(x-1,y-1));}
if (isNotBlock(x-1,y+1)) {listChildren.addElement(new Point(x-1,y+1));}
if (isNotBlock(x+1,y+1)) {listChildren.addElement(new Point(x+1,y+1));}
if (isNotBlock(x+1,y-1)) {listChildren.addElement(new Point(x+1,y-1));}
return listChildren;
}
/*------------------------------------------------------------------------------------*/
/**
* Finds the optimal path between 2 points.
*
* @param pointStart baginning of the path (in CELL units)
* @param pointGoal end of the path (in CELL units)
*/
static public List findPath(Point pointStart, Point pointGoal) {
if (SHOW_DEBUG)
System.out.println("AStarDouble::findPath");
if (aStar==null)
aStar=new AStarDouble();
//if ( (!isNotBlock(pointStart.x, pointStart.y)) || (!isNotBlock(pointGoal.x, pointGoal.y)) )
if (SHOW_DEBUG)
System.out.print(pointGoal);
if ( (!aStar.isValidGoal(pointGoal)) ) {
if (SHOW_DEBUG)
System.err.println("error : invalid point");
return null;
}
if (SHOW_DEBUG)
System.out.println(" -> " + pointGoal);
NodeDouble solution = aStar.searchNode(pointStart, pointGoal);
return aStar.getPath(solution);
}
/*------------------------------------------------------------------------------------*/
/**
* constructs the path from the start node to the node n
*/
private List getPath(NodeDouble n) {
List result;
if (n == null) {
result = new List();
} else {
result = getPath(n.parent);
result.addElement(n.point);
}
return result;
}
/**
* prints the AStar path
*/
public String toString(List path) {
Point pathPoint;
String result = "";
for (int i=0; i<path.size(); i++) {
pathPoint = (Point) path.elementAt(i);
result += "path["+i+"] = (" + pathPoint.x + "," + pathPoint.y + ")\n";
}
return result;
}
/*------------------------------------------------------------------------------------*/
/**
* initializes the array "map" with a BufferedImage
*/
public void initMask(BufferedImage maskBuffImg, int myMapWidth, int myMapHeight)
{
mapWidth = myMapWidth;
mapHeight = myMapHeight;
map = null;
map = new boolean[myMapWidth][myMapHeight];
for (int i=0; i<myMapWidth; i++)
{
for (int j=0; j<myMapHeight; j++)
{
map[i][j] = (maskBuffImg.getRGB(i, j)==-1) ? false: true; // not blocked
}
}
}
/** To set the mask
*/
static public void setMask( boolean mask[][] ) {
if (aStar==null)
aStar = new AStarDouble();
map = mask;
mapWidth = mask.length;
mapHeight = mask[0].length;
}
/*------------------------------------------------------------------------------------*/
static public List smoothPath(List path) {
return aStar.smoothPath1(path);
}
/** SMOOTH PATH ALGO FROM GAMASUTRA **/
/** To smooth a path.
* @param path a previously created path via Astar
* @return smoothed path...
*/
public List smoothPath1( List path ) {
if ( (path==null) || (path.size()<3) )
return path;
List smoothedPath = new List( path.size() );
Point checkPoint = (Point) path.elementAt(0);
int index = 1;
smoothedPath.addElement( path.elementAt(0) ); // first point
while ( index+1<path.size() )
if ( walkable( checkPoint, (Point) path.elementAt(index+1) ) )
index++; // no need for this point, we check the next one
else {
checkPoint = (Point) path.elementAt(index);
smoothedPath.addElement( checkPoint ); // point needed
index++;
}
smoothedPath.addElement( path.elementAt(index) ); // end point
return smoothedPath;
}
/** Returns true if we can walk directly from point A to point B.
*/
private boolean walkable( Point a, Point b ) {
float cosinus = 0;
float sinus = 0;
if ((a.x == b.x) && (a.y == b.y)) {
return true;
}
// 1 - compute angle between the two points...
if (b.x == a.x) {
if (b.y>a.y) {
cosinus = 0;
sinus = 1;
}
else if (b.y<a.y) {
cosinus = 0;
sinus = -1;
}
//else angle = 0.0f;
} else {
double angle = Math.atan( (double) (b.y-a.y)/(b.x-a.x) );
if (b.x<a.x) {
cosinus = (float) -Math.cos(angle);
sinus = (float) -Math.sin(angle);
} else {
cosinus = (float) Math.cos(angle);
sinus = (float) Math.sin(angle);
}
}
// 2 - check points along the path every 0.25 pixels...
float rfin = (float) Math.sqrt( (b.y-a.y)*(b.y-a.y) + (b.x-a.x)*(b.x-a.x) );
for ( float r=0.25f; r<rfin; r +=0.25f ) {
if ( !isNotBlock( (int) (a.x+r*cosinus), (int) (a.y+r*sinus) ) ) {
return false;
}
}
return true; // success ! found valid path between these two points!
}
/*------------------------------------------------------------------------------------*/
/** To dynamically modify the mask setting all pixels of a rectangle to a boolean value
*
* @param r the rectangle to fill (in screen pixels coordinate)
* @param maskTileSize the CELL size (in pixel units)
* @param value new value of the pixels
*/
private synchronized void changeRectangle(Rectangle r, int maskTileSize, boolean value) {
int cx = (int) (r.x/maskTileSize);
int cy = (int) (r.y/maskTileSize);
int cWidth = (int) (r.getWidth()/maskTileSize);
if( cWidth==0 ) cWidth=1;
int cHeight = (int) (r.getHeight()/maskTileSize);
if( cHeight==0 ) cHeight=1;
if (SHOW_DEBUG)
System.out.println("cWidth = " + cWidth + " cHeight = " + cHeight);
for (int i=0; i<cWidth; i++)
for (int j=0; j<cHeight; j++)
if(cx+i<map.length && cy+j<map[0].length)
map[cx+i][cy+j] = value;
}
/** To dynamically modify the mask setting all pixels
* of a rectangle to false
*
* @param r the rectangle to fill (in screen pixels coordinate)
*/
static public void fillRectangle(Rectangle r) {
aStar.changeRectangle(r, tileSize, false);
}
/** To dynamically modify the mask setting all pixels
* of a rectangle to true
*
* @param r the rectangle to clean (in screen pixels coordinate)
*/
static public void cleanRectangle(Rectangle r) {
aStar.changeRectangle(r, tileSize, true);
}
/*------------------------------------------------------------------------------------*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -