比方说定义格子的长度(W=80像素),高度(H=40像素)
Constants.TILE_WIDTH = 80;
Constants.TILE_HEIGHT= 40;
Constants.TILE_WIDTH_2 = 80/2;
Constants.TILE_HEIGHT_2= 40/2;
1:格子坐标与像素坐标的互相转换公式
1.1:格子坐标转像素坐标
/**
* 像素坐标转换成斜45度的格子坐标
* @param px 像素X坐标
* @param py 像素Y坐标
* @return
*/
public static short[] pixToTile(int px,int py){
int cx = (px/Constants.TILE_WIDTH)*Constants.TILE_WIDTH+Constants.TILE_WIDTH_2;
int cy = (py/Constants.TILE_HEIGHT)*Constants.TILE_HEIGHT+Constants.TILE_HEIGHT_2;
int rx = (px-cx)*Constants.TILE_HEIGHT_2;
int ry = (py-cy)*Constants.TILE_WIDTH_2;
int tx,ty;
if((Math.abs(rx)+Math.abs(ry))<=(Constants.TILE_WIDTH*Constants.TILE_HEIGHT/4)){
tx = px/Constants.TILE_WIDTH;
ty = (py/Constants.TILE_HEIGHT)*2;
}else{
px = px-Constants.TILE_WIDTH_2;
tx = px/Constants.TILE_WIDTH+1;
py = py-Constants.TILE_HEIGHT_2;
ty = (py/Constants.TILE_HEIGHT)*2+1;
}
tx = tx-(ty&1);
return new short[]{(short)tx,(short)ty};
}
1.2:像素坐标转格子坐标
/**
* 斜45度的格子坐标转换成像素坐标
* @param tx 斜45度的格子X坐标
* @param ty 斜45度的格子Y坐标
* @return
*/
public static short[] tileToPix(int tx,int ty){
int px=(tx*Constants.TILE_WIDTH+((ty&1)+1)*(Constants.TILE_WIDTH/2));
int py=(ty+1)*(Constants.TILE_HEIGHT/2);
return new short[]{(short)px,(short)py};
}
2:两格子坐标四方向相差的格子数计算
/**
* 忽略地图地形(计算两个格子之间经过的格子数)
* @param bx 开始格子X坐标
* @param by 开始格子Y坐标
* @param ex 目标格子X坐标
* @param ey 目标格子Y坐标
* @return
*/
public static int getTileNumFromTile(short bx,short by,short ex,short ey){
short[] beginPix = tileToPix(bx,by);
short[] endPix = tileToPix(ex,ey);
int subX = Math.abs(endPix[0]-beginPix[0])/(Constants.TILE_WIDTH/2);
int subY = Math.abs(endPix[1]-beginPix[1])/(Constants.TILE_HEIGHT/2);
return Math.max(subX, subY);
}
3:靠近某目标格子的相关计算
/**
* 获取以此格子坐标(x,y)为中心的四个方向的其他格子坐标
* @param x
* @param y
* @return
*/
public static short[][] getNext4(short x,short y){
short[][] nextXy= new short[4][2];
//Y坐标偶数时 X坐标减1
if(y%2==0){
short preX = (short)(x-1);
short preY = (short)(y-1);
short nexY = (short)(y+1);
nextXy[0]=new short[]{preX,preY};
nextXy[1]=new short[]{preX,nexY};
nextXy[2]=new short[]{x,preY};
nextXy[3]=new short[]{x,nexY};
}else{
short preY = (short)(y-1);
short nexY = (short)(y+1);
short nextX = (short)(x+1);
nextXy[0]=new short[]{x,preY};
nextXy[1]=new short[]{x,nexY};
nextXy[2]=new short[]{nextX,preY};
nextXy[3]=new short[]{nextX,nexY};
}
return nextXy;
}
/**
* 找出最短格子路线
* @param map 地图数据
* @param begin 起点位置数据
* @param end 目标位置格子坐标
* @param moveAbility 可移动的格子数
* @param areaNum 所占格子数
* @param isOmit 忽略地形
* @return
*/ public static Object[] findMinTileLine(byte[][]map,SlgNode begin,short[] end,byte moveAbility,byte areaNum,boolean isOmit){
//最小格子数
int minNums = getTileNumFromTile(begin.getTx(),begin.getTy(),end[0],end[1]);
if(minNums<2)return null;
if(areaNum>1){
short[][] infos = getTopArea(begin.getTx(),begin.getTy(),areaNum);
for(int i=1;i<infos.length;i++){
int tmpNums = getTileNumFromTile(infos[i][0],infos[i][1],end[0],end[1]);
if(tmpNums<minNums){
minNums = tmpNums;
if(minNums < 2) return null;
}
}
}
int curr=0;
SlgNode node = begin;
while(curr<moveAbility){
//找出周围四个格子离目标的位置
short[][] data = getNext4(node.getTx(),node.getTy());
SlgNode minNode = null;
int omit = (isOmit?2:1);
for(int i=0;i<data.length;i++){
short tx =data[i][0],ty =data[i][1];
//格子位置是否合法(没有被障碍物阻止)
if(ty>=0&&ty<map.length&&tx>=0&&tx<map[0].length&&map[ty][tx]<omit){
int tmpNums = getTileNumFromTile(tx,ty,end[0],end[1]);
boolean isFlag = true;
//如果是占用多格子的检测其他的格子是否合法
if(areaNum>1){
short[][] infos = getTopArea(tx,ty,areaNum);
for(int j=1;j<infos.length;j++){
short tx0 = infos[j][0],ty0=infos[j][1];
if(ty0<map.length&&tx0 <map[0].length && ty0>=0&&tx0>=0&&map[ty0][tx0]<omit){
if(tmpNums>1){
int tmpNums0 = getTileNumFromTile(tx0,ty0,end[0],end[1]);
if(tmpNums0<tmpNums)tmpNums = tmpNums0;
}
}else{
isFlag = false;break;
}
}
}
if(tmpNums<minNums && isFlag){
minNode= new SlgNode(tx,ty,(byte)(node.getLen()+1));
minNode.setParent(node);
if(tmpNums<2)return new Object[]{minNode,tmpNums};
minNums = tmpNums;
}
}
}
if(minNode==null)return curr==0?null:new Object[]{minNode,minNums};
curr++;
node = minNode;
}
return new Object[]{node,minNums};
}
/**
* SLG移动格子坐标数据定义
* @author Administrator
*
*/
public class SlgNode implements Comparable<SlgNode>{
//格子坐标
private short tx;
private short ty;
//父节点
private SlgNode parent;
//步长
private byte len;
public SlgNode(){
}
public SlgNode(short tx,short ty,byte len){
this.tx = tx;
this.ty= ty;
this.len = len;
}
public short getTx() {
return tx;
}
public void setTx(short tx) {
this.tx = tx;
}
public short getTy() {
return ty;
}
public void setTy(short ty) {
this.ty = ty;
}
public SlgNode getParent() {
return parent;
}
public void setParent(SlgNode parent) {
this.parent = parent;
}
public byte getLen() {
return len;
}
public void setLen(int len) {
this.len = (byte)len;
}
public static String getCode(int x,int y){
return x+"_"+y;
}
public String getCode(){
return getCode(tx,ty);
}
public String toString(){
StringBuilder path = new StringBuilder().append("[").append(tx).append(",").append(ty).append("][").append(len).append("]");
if(this.parent!=null){
path.append("->").append(this.parent.toString());
}
return path.toString();
}
public int compareTo(SlgNode o) {
if(len>0 && o.getLen()>0){
return len-o.getLen();
}else if(o.getLen()>0){
return 1;
}
return 0;
}
}
斜45度游戏涉及到计算
最新推荐文章于 2021-03-29 17:02:08 发布