最近在读《我所理解的cocos2dx》一书,感觉挺不错的,推荐一下,以下理解有不少地方受书中内容启发。 这里只写我自己理解的部分,基础部分如果有不懂的,请参考cocos2dx官方文档,写得也很详细。cocos2dx官方文档
设计分辨率与缩放策略
cocos2dx 通过设置设计分辨率来支持多屏幕分辨率适配,引擎底层会根据当前实际的屏幕分辨率通过相应的缩放策略处理设计分辨率的缩放。
/** * Set the design resolution size. * @param width Design resolution width. * @param height Design resolution height. * @param resolutionPolicy The resolution policy desired,you may choose: * [1] EXACT_FIT Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio,your game view will be stretched. * [2] NO_BORDER Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio,two areas of your game view will be cut. * [3] SHOW_ALL Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio,two black borders will be shown. */ virtual void setDesignResolutionSize(float width,float height,ResolutionPolicy resolutionPolicy);
对于EXACT_FIT,NO_BORDER,SHOW_ALL,三种缩放方式现在项目中用得比较少。EXACT_FIT会拉伸资源,NO_BORDER适用于设计分辨率与屏幕分辨率长宽比例一致的情况,有些项目是使用了多套设计分辨率以及多套资源来保证屏幕接近等比缩放。SHOW_ALL则会导致较窄一边出现黑边。这三种方式的优点是UI的位置在屏幕中一旦确定,就不需要随着屏幕分辨率的不同而更改。
对于这三种方式,设计分辨率就是绘制区域的大小,屏幕绘制的原点是设计分辨率对应区域的原点。当出现黑边的时候,黑边是在绘图区域之外的,程序无法直接在黑边上面绘制一些背景,广告什么的。之前有见过一篇文章是介绍如何在黑边上面绘制,但步骤比较麻烦一点,有兴趣可以搜索一下。
常用的缩放策略
if (_resolutionPolicy == ResolutionPolicy::NO_BORDER) { _scaleX = _scaleY = MAX(_scaleX,_scaleY); } else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL) { _scaleX = _scaleY = MIN(_scaleX,_scaleY); } else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) { _scaleX = _scaleY; _designResolutionSize.width = ceilf(_screenSize.width/_scaleX); } else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) { _scaleY = _scaleX; _designResolutionSize.height = ceilf(_screenSize.height/_scaleY); }
可以看到,使用FIXED_WIDTH(FIXED_HEGITH)方式,在保证了长宽缩放比例一致的情况下,修改了设计分辨率的尺寸!
修改设计分辨率会带来两方面的影响:
1,屏幕中的UI元素的坐标改变了。例如FIXED_WIDHT时,当设计尺寸为1280*720的时候,把一个元素放到中心点640*360的位置,随着屏幕实际分辨率的变化,这个元素可能已经不在中心点的位置,可能往上平移了。所以如果UI元素有跟背景位置相关联的时候,就不能直接写绝对坐标了,而是要使这个坐标值能够适应这种屏幕变化。
2,绘制区域改变了。改变设计分辨率就意味着绘制区域的改变,如果资源的分辨率没有改变,并且这个资源是对齐到屏幕中心点位置,那么屏幕上下(或者左右)就会留有黑边。为什么会有黑边,因为绘制区域已经大于资源的分辨率了,例如FIXED_WIDTH时,设计尺寸和资源(一张背景图)分辨率都是1280*720,屏幕分辨率是1280*800,那么setDesignResolutionSize后,设计分辨率就变成了1280*800,这张背景图放到屏幕中心点后,高度与设计分辨率差了80,所以上下会有40像素区域没有任何图像可以绘制的。这就造成了跟使用SHOW_ALL一样的效果,但实质上却是区别很大,SHOW_ALL的黑边不能绘制,FIXED_XXX的黑边只是因为资源分辨率不够,而没有被绘制。如果这时候,把这张资源分辨率换成1280*800,就会发现没有黑边了。完美适配屏幕。
使用FIXED_XXX需要注意的问题:
1,使用一张更大的背景图,例如当前设计分辨率是1280*720,使用FIXED_WIDTH方式,想要适配主流屏幕,背景图至少需要使用1280*960分辨率,4:3的屏幕应该是市场上长宽比最小的了。这样屏幕上下就不会有黑边存在。
2,尽量不使用绝对坐标,但如果元素的位置是跟屏幕底部有关,那也可以使用绝对坐标。例如游戏分为上,中,下三部分区域,下面的区域不变,如果屏幕高度变化了,中间的区域就相对拉大一点(具体也要跟设计背景图以及游戏本身表现有关)。这样的话,最下面部分的UI元素完全可以使用绝对坐标。同样,也可以使用屏幕中心点上下偏移多少坐标,来设置元素位置。
3,使用visibleSize,它返回的始终是根据当前设备分辨率调整的可视区域的分辨率。
4,如果还是想使用1280*720来设计坐标值,可以写个宏来计算坐标的偏移量。根据当前可视区域的高度与设计尺寸(1280*720,不是引擎修改后的尺寸)的高度比来计算元素在拉伸后的坐标。
以上问题根据项目的实际情况选择,只是自己的见解,有不足的请再帮忙补充一下。
资源分辨率的缩放
/** The size in pixels of the surface. It could be different than the screen size. High-res devices might have a higher surface size than the screen size. Only available when compiled using SDK >= 4.0. @since v0.99.4 */ void setContentScaleFactor(float scaleFactor);设置资源的缩放因子。当缩放因子是1时,表示1像素的图片资源将占用1像素的设计分辨率。按照上述分辨率,应设置缩放因子为800/1280=0.625,即图片资源显示在屏幕上时1像素的资源要占用屏幕上将近2像素的分辨率。同时,资源的长度和宽度也会按比例拉伸,所以程序中需要依赖资源的contentSize来设置位置的时候,需要按照宽度或者高度的几分之几来设置。例如一张图片是50*50的,按照如上设置后,在程序中获取的宽度和高度可能是80*80了。 Texture2D的getContentSize方法将纹理的实际分辨率转化为了设计分辨率。
第一次发技术贴,请大家多指教,有问题一起讨论!