代码改变世界

[转]45度菱形地图屏幕坐标转换为逻辑坐标及直角坐标的方法

2009-08-06 23:16  宝宝合凤凰  阅读(3547)  评论(0)    收藏  举报

45度菱形地图屏幕坐标转换为逻辑坐标及直角坐标的方法

标签45度  地图  flash  坐标  菱形  直角  屏幕  逻辑  3小时前
看到有同学提问 hfMapeditor 的屏幕点击坐标转换为直角坐标的方法
http://www.b4en.com/home/link.php?url=http://www.eb163.com%2Fclub%2Fthread-4281-1-1.html

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

得到的图应该是这样的:

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

 


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

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


图上绿点(是高亮度绿色,不是暗绿色)是每块地图元素的起点,第一行的行坐标是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:

 

 
 

 

而得到的逻辑坐标就是把了斜45度得到的实际坐标么?当然不是···

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


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

 

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

 

 

 

                //地图点击事件
                public function onClick(event:Event):void{
//                        var __nodePointoint = GameMapUtils.getCellPoint(_cellWidth,_cellHeight,event.currentTarget.mouseX,event.currentTarget.mouseY);
                        var _nodeRPointoint = GameMapUtils.getDirectPointByPixel(_cellWidth,_cellHeight,event.currentTarget.mouseX,event.currentTarget.mouseY,_row);
                        var __nodeX:int = _nodeRPoint.x;
                        var __nodeY:int = _nodeRPoint.y;
                       
//                        var __rolePointoint = GameMapUtils.getCellPoint(_cellWidth,_cellHeight,_player.x,_player.y);
                        var _roleRPointoint = GameMapUtils.getDirectPointByPixel(_cellWidth,_cellHeight,_player.x,_player.y,_row);
                        var __roleX:int = _roleRPoint.x;
                        var __roleY:int = _roleRPoint.y;
                        var __length:int;
                        _player.moveToX = event.currentTarget.mouseX;
                        _player.moveToY = event.currentTarget.mouseY;
//                        trace("__nodeX : " + __nodeX);
//                        trace("__nodeY : " + __nodeY);
//                        trace("__roleX : " + __roleX);
//                        trace("__roleY : " + __roleY);
                        var maxPoint = GameMapUtils.getMaxDirectPoint(_row,_col);
                        if(__nodeX>=0 && __nodeX<maxP.x && __nodeY>=0 && __nodeY<maxP.y && _roadSeeker.value(__nodeX, __nodeY)==0){
                                _roadArr =_roadSeeker.path8(new Point(__roleX, __roleY), new Point(__nodeX, __nodeY));
                                __length = _roadSeeker.path.length;
//                                trace(__length);
                                if(__length>0){
                                        _pathIndex = 1;
//                                        trace("_roadSeeker.path[_pathIndex].x : " + _roadSeeker.path[_pathIndex].x);
//                                        trace("_roadSeeker.path[_pathIndex].y : " + _roadSeeker.path[_pathIndex].y);
//                                        trace("px : " + _roadMap.getValue(_roadSeeker.path[_pathIndex].y+""+_roadSeeker.path[_pathIndex].x).px);
//                                        trace("py : " + _roadMap.getValue(_roadSeeker.path[_pathIndex].y+""+_roadSeeker.path[_pathIndex].x).py);

                                        var px:int =  _roadMap.getValue(_roadSeeker.path[_pathIndex].y+"-"+_roadSeeker.path[_pathIndex].x).px;
                                        var py:int =  _roadMap.getValue(_roadSeeker.path[_pathIndex].y+"-"+_roadSeeker.path[_pathIndex].x).py;
                                       
//                                        trace("px : " + px);
//                                        trace("py : " + py);
                                        _player.addEventListener(WalkEvent.WALK_END, onMoveOver);
                                        _player.addEventListener(WalkEvent.ON_WALK,checkDep);
                                        var tpoint = GameMapUtils.getPixelPoint(_cellWidth,_cellHeight,px,py);
                                        _player.moveTo(tp.x, tp.y+_cellHeight);
                                }
                        }
                }