posts - 311, comments - 0, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

屏幕坐标位置的确定用公式计算:
屏幕的x坐标=地图格子逻辑数组中的位置X * 格子宽度
屏幕的y坐标=地图格子逻辑数组中的位置Y * 格子高度/2

得到的图应该是这样的:

那么这个公式是怎样得到呢?




这个地图有5行,看着这个地图你会想,怎么拼图才能将地图拼出来。再画张图来演示:






从这张图可以看出,拼图时从左到右,从上到下,跟正规的矩形拼图一样,唯一同的是,地图元素与元素之间有重叠,看看第一行和第二行之间,第二行的地图元素会压在第一行的元素上,而第三行的的地图元素则压在第二行的元素上。所以,只要找到正确的公式,你就能正确地设计程序,再来一张图:





图上绿点(是高亮度绿色,不是暗绿色)是每块地图元素的起点,第一行的行坐标是0,第二行的行坐标是1,第三行的行坐标是2,......由这些行坐标决定你的地图元素的起点,从这个规律中看出行坐标0,和行坐标2的横向坐标X的起点是一样的是0,行坐标为1的起点是向右移半块地图元素。
再从纵向坐标找规律,看行坐标0和行坐标2,两块地图元素之间的距离刚好是一块地图元素的高。再看看行坐标0和行坐标1,两块地图元素之间的距离刚好是半块地图元素的高。所以,计算每块地图元素的位置,你的转换屏幕坐标和逻辑公式刚好是:
logic.y = ( 2 * stage.y ) / TileHeigth;
logic.x = ( stage.x / TileWidth ) - ( logic.y & 1 ) * ( TileWidth / 2 );
stage.x = logic.x * TileWidth + ( logic.y & 1) * ( TileWidth / 2 );
stage.y = logic.y * TileHeigth / 2;
其中TileHeigth和TileWidth是菱形的高和宽,这样你可以再尝试着定义(0,1),(0,2),(0,3)等点,和得到的结果完全一样···

重要:
首先以上的公式只适用于Staggered斜45度角地图,而slide,和Diamond形地图,这个公式要稍加修改才能用。
Staggered:



Slide:



Diamond:




而得到的逻辑坐标就是把了斜45度得到的实际坐标么?当然不是···
仔细观察,如果我们想用一个直角的坐标来表示这个地图,那么大家可能开发起来也更加直观一些,看这个坐标表示出来的y轴都是扭曲的用起来实在不爽,那么我们来将它转换到直角坐标,那么再来加上寻路等算法都没有任何难度了

首先我们将地图的高进行转换,这个转换主要是将菱形还原成正方形,例如菱形的高宽比是2:1,那么在地图上则需要将地图高度扩大一倍,然后旋转-45度,那么得到对应坐标如下




我们更加仔细的对这个图的坐标进行

 1 /*
 2  
 3 * @author myth815 
 4 */ 
 5 package ContainerObjectManager 
 6 
 7 import flash.geom.Point; 
 8 import Math; 
 9 public class PointExchange 
10 
11 private static var TileWidth : int = 60
12 private static var TileHeigth : int = 30
13 public function PointExchange() 
14 
15 //this Class not allow init! 
16 
17 
18 public static function StageToLogic(stage:Point):Point 
19 
20 var logic : Point = new Point; 
21 logic.y = ( 2 * stage.y ) / TileHeigth; 
22 logic.x = ( stage.x / TileWidth ) - ( logic.y & 1 ) * ( TileWidth / 2 ); 
23 return logic; 
24 
25 
26 public static function LogicToStage(logic:Point):Point 
27 
28 var stage : Point = new Point; 
29 stage.x = logic.x * TileWidth + ( logic.y & 1* ( TileWidth / 2 ); 
30 stage.y = logic.y * TileHeigth / 2
31 return stage; 
32 
33 
34 

标注:

 

  1 比方说定义格子的长度(W=80像素),高度(H=40像素)    
  2 Constants.TILE_WIDTH = 80;    
  3 Constants.TILE_HEIGHT= 40;    
  4 1:格子坐标与像素坐标的互相转换公式    
  5 1.1:格子坐标转像素坐标   
  6    /**  
  7      * 像素坐标转换成斜45度的格子坐标  
  8      * @param px  像素X坐标  
  9      * @param py  像素Y坐标  
 10      * @return  
 11      */  
 12     public static short[] pixToTile(int px,int py){   
 13         int ty= 2*py/Constants.TILE_HEIGHT-1;   
 14         if(ty<0){   
 15             log.error("ty:"+py);   
 16             ty = 0;   
 17         }   
 18         int tx= (px-(ty&1)*(Constants.TILE_WIDTH/2))/Constants.TILE_WIDTH;   
 19         if(tx<0){   
 20             log.error("tx:"+px);   
 21             tx = 0;   
 22         }   
 23         return new short[]{(short)tx,(short)ty};   
 24     }   
 25 1.2:像素坐标转格子坐标   
 26 /**  
 27      * 斜45度的格子坐标转换成像素坐标  
 28      * @param tx 斜45度的格子X坐标  
 29      * @param ty 斜45度的格子Y坐标  
 30      * @return  
 31      */  
 32     public static short[] tileToPix(int tx,int ty){   
 33         int px=(tx*Constants.TILE_WIDTH+((ty&1)+1)*(Constants.TILE_WIDTH/2));   
 34         int py=(ty+1)*(Constants.TILE_HEIGHT/2);   
 35         return new short[]{(short)px,(short)py};   
 36     }   
 37   
 38   
 39   
 40 2:两格子坐标四方向相差的格子数计算    
 41   
 42 /**  
 43      * 忽略地图地形(计算两个格子之间经过的格子数)  
 44      * @param bx 开始格子X坐标  
 45      * @param by 开始格子Y坐标  
 46      * @param ex 目标格子X坐标  
 47      * @param ey 目标格子Y坐标  
 48      * @return  
 49      */  
 50     public static int getTileNumFromTile(short bx,short by,short ex,short ey){   
 51         short[] beginPix =  tileToPix(bx,by);   
 52         short[] endPix =  tileToPix(ex,ey);   
 53         int subX = Math.abs(endPix[0]-beginPix[0])/(Constants.TILE_WIDTH/2);   
 54         int subY = Math.abs(endPix[1]-beginPix[1])/(Constants.TILE_HEIGHT/2);   
 55         return Math.max(subX, subY);   
 56     }   
 57   
 58 3:靠近某目标格子的相关计算    
 59   
 60 /**  
 61      * 获取以此格子坐标(x,y)为中心的四个方向的其他格子坐标  
 62      * @param x  
 63      * @param y  
 64      * @return  
 65      */  
 66     public static short[][] getNext4(short x,short y){   
 67         short[][] nextXy= new short[4][2];   
 68         //Y坐标偶数时 X坐标减1   
 69         if(y%2==0){   
 70             short preX = (short)(x-1);   
 71             short preY = (short)(y-1);   
 72             short nexY = (short)(y+1);   
 73             nextXy[0]=new short[]{preX,preY};   
 74             nextXy[1]=new short[]{preX,nexY};   
 75             nextXy[2]=new short[]{x,preY};   
 76             nextXy[3]=new short[]{x,nexY};   
 77         }else{   
 78             short preY = (short)(y-1);   
 79             short nexY = (short)(y+1);   
 80             short nextX = (short)(x+1);   
 81             nextXy[0]=new short[]{x,preY};   
 82             nextXy[1]=new short[]{x,nexY};   
 83             nextXy[2]=new short[]{nextX,preY};   
 84             nextXy[3]=new short[]{nextX,nexY};   
 85         }   
 86         return nextXy;   
 87     }   
 88   
 89   
 90 /**  
 91      * 找出最短格子路线  
 92      * @param map 地图数据  
 93      * @param begin 起点位置数据  
 94      * @param end 目标位置格子坐标  
 95      * @param moveAbility 可移动的格子数  
 96      * @param areaNum 所占格子数  
 97      * @param isOmit 忽略地形  
 98      * @return  
 99      */ public static Object[] findMinTileLine(byte[][]map,SlgNode begin,short[] end,byte moveAbility,byte areaNum,boolean isOmit){   
100         //最小格子数   
101         int minNums = getTileNumFromTile(begin.getTx(),begin.getTy(),end[0],end[1]);   
102         if(minNums<2)return null;   
103         if(areaNum>1){   
104             short[][] infos = getTopArea(begin.getTx(),begin.getTy(),areaNum);   
105             for(int i=1;i<infos.length;i++){   
106                 int tmpNums = getTileNumFromTile(infos[i][0],infos[i][1],end[0],end[1]);   
107                 if(tmpNums<minNums){   
108                     minNums = tmpNums;   
109                     if(minNums < 2return null;   
110                 }   
111             }   
112         }   
113         int curr=0;   
114         SlgNode node = begin;   
115         while(curr<moveAbility){   
116             //找出周围四个格子离目标的位置   
117             short[][] data = getNext4(node.getTx(),node.getTy());   
118             SlgNode minNode = null;   
119                             int   omit = (isOmit?2:1);   
120   
121             for(int i=0;i<data.length;i++){   
122                 short tx =data[i][0],ty =data[i][1];   
123                                 //格子位置是否合法(没有被障碍物阻止)   
124                 if(ty>=0&&ty<map.length&&tx>=0&&tx<map[0].length&&map[ty][tx]<omit){   
125                     int tmpNums = getTileNumFromTile(tx,ty,end[0],end[1]);   
126                     boolean isFlag = true;   
127                     //如果是占用多格子的检测其他的格子是否合法   
128                     if(areaNum>1){   
129                         short[][] infos = getTopArea(tx,ty,areaNum);   
130                         for(int j=1;j<infos.length;j++){   
131                             short tx0 = infos[j][0],ty0=infos[j][1];   
132                             if(ty0<map.length&&tx0 <map[0].length && ty0>=0&&tx0>=0&&map[ty0][tx0]<omit){   
133                                 if(tmpNums>1){   
134                                     int tmpNums0 = getTileNumFromTile(tx0,ty0,end[0],end[1]);   
135                                     if(tmpNums0<tmpNums)tmpNums = tmpNums0;   
136                                 }   
137                             }else{   
138                                 isFlag = false;break;   
139                             }   
140                         }   
141                     }   
142                     if(tmpNums<minNums && isFlag){   
143                         minNode= new SlgNode(tx,ty,(byte)(node.getLen()+1));   
144                         minNode.setParent(node);   
145                         if(tmpNums<2)return new Object[]{minNode,tmpNums};   
146                         minNums = tmpNums;   
147                     }   
148                 }   
149             }   
150             if(minNode==null)return curr==0?null:new Object[]{minNode,minNums};   
151             curr++;   
152             node = minNode;   
153         }   
154         return new Object[]{node,minNums};   
155     }   
156   
157   
158   
159 /**  
160  * SLG移动格子坐标数据定义  
161  * @author Administrator  
162  *  
163  */  
164 public class SlgNode implements Comparable<SlgNode>{   
165     //格子坐标   
166     private short tx;   
167     private short ty;   
168     //父节点   
169     private SlgNode parent;   
170     //步长   
171     private byte len;   
172        
173     public SlgNode(){   
174            
175     }   
176        
177        
178     public SlgNode(short tx,short ty,byte len){   
179         this.tx = tx;   
180         this.ty= ty;   
181         this.len = len;   
182     }   
183        
184     public short getTx() {   
185         return tx;   
186     }   
187     public void setTx(short tx) {   
188         this.tx = tx;   
189     }   
190     public short getTy() {   
191         return ty;   
192     }   
193     public void setTy(short ty) {   
194         this.ty = ty;   
195     }   
196     public SlgNode getParent() {   
197         return parent;   
198     }   
199     public void setParent(SlgNode parent) {   
200         this.parent = parent;   
201     }   
202     public byte getLen() {   
203         return len;   
204     }   
205     public void setLen(int len) {   
206         this.len = (byte)len;   
207     }   
208        
209     public static String getCode(int x,int y){   
210         return x+"_"+y;   
211     }   
212        
213     public String getCode(){       
214         return getCode(tx,ty);   
215     }   
216        
217     public String toString(){   
218         StringBuilder path = new StringBuilder().append("[").append(tx).append(",").append(ty).append("][").append(len).append("]");   
219         if(this.parent!=null){   
220             path.append("->").append(this.parent.toString());   
221         }   
222         return path.toString();   
223     }   
224   
225     public int compareTo(SlgNode o) {   
226         if(len>0 && o.getLen()>0){   
227             return len-o.getLen();   
228         }else if(o.getLen()>0){   
229             return 1;   
230         }   
231         return 0;   
232     }   
233 }  
234