本站文章均为 ftyszyx 原创,转载务必在明显处注明: 原文链接: http://blog.csdn.net/ftyszyx/article/details/9020101
在游戏中,为了在二维平面呈现立体效果常常需要使用45度角地图,最近有用到,原本以为很简单,结果搞了好几天才搞明白,因此记录下,以防以后忘记
首先要清楚几个概念:
如下是一张地图
地图宽:size_W
地图高:size_H
地图块高:tile_H
地图块宽:tile_W
具体如上图所示。
现在我们假设地图上有一点A,屏幕坐标第的原理在O点基向量为(X,Y),地图坐标系的原点在M点,基向量分别为(MX,MY)如下图:(注意,粗体是向量)
我们现在已知A点的屏幕坐标(x,y),地图原理M的屏幕坐标(size_W/2,size_H)要求A点的地图坐标(相对于地图坐标系),假设为(m,n)
因MA=mMX+nMY
而
MX=tile_H/2X+(-tile_W/2)Y
MY=(-tile_H/2)X+(-tile_W/2)Y
所以可得MA的屏幕坐标表示:(m-n)*tile_H/2 X +(m+n)*(-tile_W/2) Y
因OA=OM+MA
所以可得OA=(size_W/2+(m-n)*tile_H/2 ) X +(size_H+(m+n)*(-tile_W/2) ) Y,
于是有了这两个等式:
x=size_W/2+(m-n)*tile_H/2
y=size_H+(m+n)*(-tile_W/2)
求解可得m=(x-size_W/2)/tile_H-(y-size_H)/tile_W;
n=-(x-size_W/2)/tile_H-(y-size_H)/tile_W;
同理,也可以根据A的地图坐标求得A的屏幕坐标:
具体程序实现如下:
//将标准坐标转为地图坐标
CCPoint MapScene::converttomapPonit(float x,float y)
{
//求map原点坐标
CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
int tilewidth=map->getTileSize().width;
int tilehigh=map->getTileSize().height;
float mapOrginX=map->getPosition().x+map->getContentSize().width/2;
float mapOrginy=map->getPosition().y+map->getContentSize().height;
//O为地图的原点,A是要求的点,oa向量的值
float OA_x=x-mapOrginX;
float OA_y=y-mapOrginy;
//假设以地图的原点为初始坐标(正上方那个点),对应的所示点的坐标值为m,n
//将地图坐标(m,n)转为标准坐标,则有:
//(x,y)-(mapOrginX,mapOrginy)=m(tilewidth/2,-tilehigh/2)+n(-tilewidth/2,-tilehigh/2)
//因此m=(OA_x/(tilewidth/2)+OA_y/(-tilehigh/2)/2=OA_x/tilewidth-OA_y/tilehigh
//n=(OA_y/(-tilehigh/2)-OA_x/(tilewidth/2))/2=-(OA_y/tilehigh+OA_x/tilewidth)
float m=OA_x/tilewidth-OA_y/tilehigh;
float n=-(OA_y/tilehigh+OA_x/tilewidth);
if(m<0 ) m=0;
if(n<0) n=0;
if(m>map->getMapSize().width-1) m=map->getMapSize().width-1;
if(n>map->getMapSize().height-1) n=map->getMapSize().height-1;
return CCPoint((int)m,(int)n);
}
//将地图坐标转成屏幕坐标
CCPoint MapScene::convertTOSecenPoint(int x,int y)
{
//求map原点坐标
CCTMXTiledMap* map = (CCTMXTiledMap*) getChildByTag(kTagTileMap);
float tilewidth=map->getTileSize().width;
float tilehigh=map->getTileSize().height;
//原点下移了到方块的中心
int mapOrginX=map->getPosition().x+map->getContentSize().width/2;
int mapOrginy=map->getPosition().y+map->getContentSize().height;
if (x>map->getMapSize().width || x<0
|| y>map->getMapSize().height || y<0)
{//超出范围
return CCPoint(0,0);
}
float OA_x=(x-y)*tilewidth/2.0;
float OA_y=-(x+y)*tilehigh/2.0;
return CCPoint(mapOrginX+OA_x,mapOrginy+OA_y);
}