[转]45度菱形地图屏幕坐标转换为逻辑坐标及直角坐标的方法
2009-08-06 23:16 宝宝合凤凰 阅读(3547) 评论(0) 收藏 举报http://www.b4en.com/home/link.php?url=http://www.eb163.com%2Fclub%2Fthread-4281-1-1.html
屏幕坐标位置的确定用公式计算:
屏幕的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:


而得到的逻辑坐标就是把了斜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);
}
}
}