Cocos2d-x 3.2总结(三) TMXTileMap::getContentSize与getMapSize*getTileSize的积的异同



当你在图层中导入瓦片地图后,要计算触摸点在瓦片中的GID时,要使用公式1,还是公式2?接下来,我将讲解他们的异同和我们最终使用的公式。

1
Point  position=convertToNodeSpace(touch->getLocation());


公式1:

1
2
3
x=position.x/map->getContentSize().width * map->getMapSize().width;
                   y=map->getMapSize().height  -   position.y/map->getContentSize*map->getMapSize().height;
                   bgLayer->getTileGIDAt(Point(x,y));


公式2:

1
2
3
x=position.x / map->getTileSize().width;
                  y=(map->getMapSize().height * map->getTileSize().height - position.y) /  map->getTileSize().height;
                 bgLayer->getTileGIDAt(Point(x,y));


我以Cocos2d-x官网上的一个原创教程--《Cocos2d-x塔防游戏 -- 贼来了》为讲解的实例,这是因其代码有我讲解所需要的全部影响因素,我集中精力讲解计算公式的异同而不是花更多的时间在写出例子上。 


我们要清楚瓦片地图GID坐标系和Cocos2d-x位置的坐标系是不同的。其中瓦片地图GID是以左上角为原点,向下为y轴正方向,向右为x轴正方向,且以你建立地图时的每一块高度和宽度的乘积为一个计算单位。瓦片地图GID坐标系如图1,Cocos2d-x位置坐标系如图2。

图1:

41_316694_9b328b970bb5cd8.jpg

图2:

41_316694_2aaccc14383b085.jpg

从图1和图2中可以看出,cocos2d-x坐标中的y轴和瓦片地图中的y轴方向相反,且cocos2d-x中的坐标要转换为GID要分别除以瓦片中块的宽度和高度,得出以块为单位的位置。


接着,我们来看看TMXTileMap中的函数用法。getTileSize().width/height分别以像素为单位得出一块的宽度和高度。getMapSize().width/height分别得出在x轴方向上总的块数,在y轴方向上总的块数。所以,getTileSize().width/height * getMapSize().width/height分别得出在x轴上原始地图的总宽度和在y轴上原始地图的总高度。


接下来我们来看看getContentSize()在Cocos2d-x中源代码的注释“Returns the untransformed size of the node",中文意思就是返回没有被转变前的节点大小。但是,我在”贼来了“源码中调试得出getContentSize()意思是转变后的大小。我想是cocos2d-x中的注释是错的,估计是在transformed前面多加了un。这个调试过程在后面有讲解。


现在,我们在PlayLayer.cpp中的init()函数中添加代码1进行调试,调试结果如图3。

代码1:

1
2
3
4
5
6
7
8
9
10
11
//得到转换后的宽度大小  
float  testContentSizeWidth=map->getContentSize().width;  
       
//得到转换后的高度大小  
float  testContentSizeHeight=map->getContentSize().height;  
       
//地图在x轴上总块数乘以每块在x轴上的宽度  
float  primarySizeWidth=map->getMapSize().width * map->getTileSize().width;  
     
//地图在y轴上总块数乘以每块在y轴上的高度  
float  primarySizeHeight=map->getMapSize().height * map->getTileSize().height;


图3:

41_316694_5978c1e1daefe04.jpg

从图3中可以看出,testContentSize.Width/Height与primarySizz.Width/Height的值都不同。这里有两个问题。问题1,我们怎么就知道primarySize.Width/Height的值就是原始地图的宽度和高度?问题2,为什么testContentSize.Width/Height与primarySizz.Width/Height的值都不同。


对于问题1,我们可以打开Resources\height_864\map.tmx,在这个文件中有一下的信息。

1
<map version= "1.0"  orientation= "orthogonal"  width= "16"  height= "9"  tilewidth= "96"  tileheight= "96" >

也就是说这个地图x轴方向上有16块,y轴方向上有9块。每块的宽度为96,高度为96。所以16*96=1536,也就是primarySizeWidth的值了。9*96=864,也就是primarySizeHeight的值了。


对于问题2,如果你对cocos2d-x分辨率适配不了解的话,理解起来有点困难。你可以先阅读《Cocos2d-x 多分辨率适配完全解析》。现在我们可以在AppDelegate.cpp中的applicationDidFinishLaunching()看到代码2。


代码2:

1
2
3
4
5
glview->setDesignResolutionSize(480.0f, 320.0f, ResolutionPolicy::FIXED_HEIGHT);  
std::vector<std::string> searchPath;  
searchPath.push_back( "height_864" );  
CCFileUtils::getInstance()->setSearchPaths(searchPath);  
director->setContentScaleFactor(864.0f / 320.0f);

从代码2中可以看出源码设置了设计分辨率为(480.0f,320.0f),且ResolutionPolicy为FIXED_HEIGHT,也就说要保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。所以就有变化因子为地图高度除以设计分辨率的高度,即864.0 / 320.0=2.7。那我们又怎么样知道是放大还是缩小?由于地图原高度为864.0,而设计分辨率的高度320.0,明显为缩小,也就是说scalefactor大于0则为缩小,小于0则为放大。所以地图的原始宽度和高度都要除以这个比例,1536  /  2.7=568.8888  , 864 / 2.7=320,以上这两个值分别是getContentSize().width/height,所以说getContentSize得到的值是地图原始大小转变后的值,所以我说cocos2d-x的注释是错的。具体的转换过程如图4。


图4:

1407466526128172.jpg

在图4中,1137.7778是怎么得出来的?如果你看了《Cocos2d-x 多分辨率适配完全解析》大概就明白了。这里直接给出计算过程1536/ (864/320)  / (320/640) =1137.7778,1137.7778是cocos2d-x最终把地图按比例绘制屏幕上的宽度。而getContentSize.width/height得到的是Design solution下的大小。


那什么情况下getContentSize会得到地图原始的大小?如果你没有设置设计分辨率和变化因子,getContentSize得到的则是地图原始的大小。我们将代码2中的glview->setDesignResolutionSize(480.0f, 320.0f, ResolutionPolicy ::FIXED_HEIGHT)和director->setContentScaleFactor(864.0f / 320.0f)注释。再次调试,结果如图5。没有设置分辨率效果如图6,设置分辨率效果如7。

图5:

1407466672137885.jpg

图6:

1407466686650641.jpg

图7:

1407466701544103.jpg

从图5中可以看出,如果没有设置设计分辨率和变化因子,则getContentSize得到的值就是地图原始的大小。coco2d-x在屏幕上显示的地图也是原始的大小即没有按比例放大或缩小绘制。


从图6和7中可以看出,设置分辨率后,瓦片地图上的图形经过比例上的缩小以保持地图原始高度能完全呈现出来,地图原始宽度则有些超出了屏幕的范围,屏幕上的显示就是图4中screen resolution。转换的过程如图4所示。


有了以上的讲解后,现在我们回到公式1和公式2的分析来。公式1中,position.x除以getcontentSize.width,得出

的是position.x相对于转换或者转换的比例为1的地图宽度的比例,再乘以x轴方向上的块数就可以得出以块为单位的x坐标。公式2中position.x直接除以每一块的宽度得出以块为单位的x坐标,注意getTileSize().width是地图原始的宽度,而position.x的值是相对于地图按比例缩放后的值。如果没有设置设计分辨率和变化因子,则公式1和公式2得出的x的值都准确且相等的。如果设置了,则公式1得出的值是准确,而公式2得出的值是不准确的。


对于y轴上的分析如上,不过要注意瓦片坐标的y轴和cocos2d-x坐标的y轴方向相反。


经过以上的分析,最后得出总结。无论我们有没有设置分辨率,公式1得出的结果都是准确的。公式2在设置分辨率的情况下得出的结果是错误的(排除设置的分辨率就是地图的宽高)。所以,我们最好在计算GID时要使用公式1。



来源网址:http://www.cocoachina.com/bbs/read.php?tid=219259

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值