2013年11月4日补充:
之前写这篇博客的时候其实我还没有开始过真正的去做一个项目,主要过程还是偏向于理解原理。前几天在准备练练手时回过头来想了下这个问题,发现又有点一头雾水了,所以我觉得之前我并没有完全理解。于是又重新搜索了一下这个问题,找到一篇能够解释我之前留下疑问的博文,这里补上做修正。
地址:http://www.ityran.com/archives/4809 。
资料很多,我就不重复了,主要记录下自己在看完这些资料后,所思考的过程。
首先列出参考资料:
官方文档:http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Multi_resolution_support
泰然网上对官方文档的翻译:http://www.ityran.com/archives/3762
个人觉得最具有参考价值博文:http://blog.csdn.net/liaowenfeng/article/details/8566856
http://blog.leafsoar.com/archives/2013/05-10-19.html
OK,开始我自己的总结,首先要明白designResolutionSize和contentFactor。
designResolution可以称作设计尺寸或者设计分辨率,即我们在编写程序的时候所参考的分辨率尺寸(可以认为是一个虚拟的屏幕)。为什么要有这个概念?原因是我们的程序在实际运行的时候会遇到多种分辨率尺寸的屏幕,为了避免逐个进行适配,引进这么一个概念,方便程序设计编写。
contentFactor为我们的资源到设计尺寸映射的参数,通常都是使用实际资源的宽高与设计尺寸的宽高相比获得,具体使用宽度比还是高度比,取决于你希望哪个边优先适应好屏幕。具体效果稍后举例演示。
接下来要了解框架帮我们做适配实际做了什么,这里我先总结出来,稍后举例演示为什么是这个过程。这里可以参考http://www.haogongju.net/art/1906281,
其实过程就是分为两步,第一步是将我们所有需要绘制的资源全部根据contentFactor映射到设计分辨率上。第二步是将设计分辨率上的内容一次性的直接映射到实际设备屏幕上,映射的方式取决于setDesignResolutionSize的第三个参数。
总结的东西都很抽象,具体的还是结合例子来比较实际。假设现在我的资源背景图尺寸为1024*768(当然还有其他资源图片,但是通常都不会大于这个背景图),设计尺寸为480*320。
先来了解框架所做的第一步,这一步是把资源画到设计尺寸上,现在面对的问题是资源的宽高比和设计屏幕的宽高比不一样,所以必须考虑是根据资源的高度还是宽度来进行缩放到设计尺寸上比较合适。我们计算得出宽度比为ScaleWidth = 1024/480=2.1,高度比ScaleHeight = 768 / 320 = 2.4。假设我们以2.4作为缩放因子,那么实际上我们将资源图缩放后的尺寸为426*320,很明显,这时候设计屏幕上的宽度480>426,那么设计尺寸左右两边会有一部分空白区域。实际效果就是下图,
我们可以做个实验,将HelloCpp中的main.cpp中FrameSize更改为960*640(我的cocos2d-x版本为2.1.4,会在AppDelegate中根据FrameSize选择资源,为了使得选择的资源是1024*768的,这里选择将480*320的设计尺寸等比放大两倍的尺寸作为实际屏幕尺寸,这样无论怎样更改setDesignResolutionSize的第三个参数都不会影响从设计尺寸映射到实际屏幕尺寸的效果),然后运行可以发现效果如图所示:
可以发现左右两边确实留有空白区域了,这里要注意右下角的按钮和左下角的帧状态文字都能显示在空白区域,因为这是设计尺寸实际所拥有的,假如屏幕上的某一块并不是由设计尺寸实际映射而来,那么这一块是不能绘制任何东西的(这里我没做过实验,是官方文档上有说明)。
好了,上面是以2.4作为缩放因子的效果,假如以2.1作为缩放因子,那么资源缩放后的大小为480*365,很明显,高度超出了设计尺寸的高度,因此在设计屏幕上上下两端都超出了,仍然使用960*640作为目标尺寸,不过要注意确保缩放因子是2.1。运行HelloCpp效果如下:
好了,关于第一步我就说这么多。接下来看第二步。
前面提到了第二部从设计尺寸映射到实际屏幕尺寸的方式由setDesignResolutionSize的第三个参数决定,查看这个枚举类型的参数,一共有五种方式,这五种方式的具体说明官方文档说的很清楚,也比较容易理解。我这里就只总结下自己认为需要注意的地方。
1、除了第一种Fit模式会引起变形之外,其他的模式都是将设计尺寸按照一个缩放因子映射到实际屏幕上,区别就在于计算这个缩放因子的参数。
2、NoBorder模式就是告诉框架不要留空白框(这个空白框指的是非设计尺寸映射出来的空白框,而不是指因为资源映射到设计尺寸上时留下的空白框,前面我作实验时用的一直是这种模式,出现的空白框就是资源文件映射出来的空白框)。
3、ShowAll模式是告诉框架,我要的效果是把所有设计尺寸上的东西都显示完整,为了实现这个效果,框架理所当然的要找一个设计尺寸的宽高和目标屏幕的宽高比中较小的一个来进行缩放,这样才能显示完整。
4、FixWidth、FixHeight顾名思义就是告诉框架去适应目标屏幕的宽或者高。其实这两个模式和NoBorder以及ShowAll的区别就在于不需要框架去考虑能不能显示完整的问题,直接要求其适应宽度或者高度。NoBorder会为了不出现空白框,而选择设计尺寸的宽高和目标屏幕的宽高比中较大的一个来进行缩放,实际就是固定其中比较大的一个(不是宽,就是高)来进行缩放。同理ShowAll就是固定其中较小的一个比来进行缩放。
其实讲白了框架做的工作就是提供中间一个设计屏幕来减少从资源到实际屏幕的动态映射。既然如此,为什么从资源映射到设计尺寸不也使用五种对应的模式去指名映射方式呢?
屏幕适配必然存在资源的缩放,HelloCpp中根据实际屏幕尺寸去选择不同的资源,总体原则是选择比实际屏幕分辨率高的资源,因为缩小通常不会影响视觉效果,那如果设计尺寸比实际屏幕尺寸小,资源先绘制到设计尺寸上(缩小),然后放大到实际屏幕上,这样不会模糊吗?(前提是框架是真的先画在设计尺寸上,然后映射到实际屏幕上。)