在移动终端(智能手机)平台下开发游戏一般都会涉及到屏幕多分辨率适配问题,原因是手机款式多种多样,不同的款式存在有不同的尺寸,即使尺寸相同又可能存在不同的分辨率。
手机屏幕尺寸:指手机屏幕对角线长度。
手机分辨率:指屏幕上横、纵的总象素点数。分辨率越高,即总象素点数越多,屏幕显示效果越好。
上面我们介绍了手机尺寸和分辨率的概念,结论是手机屏幕显示效果是由尺寸和分辨率决定的。相同尺寸不同分辨率手机,分辨率越高显示效果越好;相同分辨率不同尺寸的手机,尺寸越大显示效果越差。
有了这两个概念,我们要开始探讨多分辨率适配问题。
什么是多分辨率适配问题呢?举例说明一下。
(1)有两款手机,屏幕尺寸相同,但分辨率不同;手机A分辨率为320*480,手机B分辨率为640*960。现在我要将一张分辨率为320*480的图片显示到两部手机屏幕上,结果将会如何呢?
答案:手机A会全屏显示图片,手机B只有四分之一屏幕会显示图片。
(2)有两款手机,屏幕分辨率都为320*480,但尺寸不同;手机A尺寸是5寸屏,手机B尺寸是3寸屏。现在我要将一张分辨率为320*480的图片显示到两部手机屏幕上,结果将会如何呢?
答案:手机A和手机B都全屏显示图片。
由上两个例子可以知道,多分辨率适配问题只与手机屏幕分辨率有关,与屏幕尺寸无关。如果所有手机都采用相同分辨率,那么将不存在多分辨率适配问题。但事实上,这肯定是不可能的。
所以,我们在开发过程中形容手机屏幕大小,可以忽略屏幕的尺寸,只使用分辨率。
那么我们解决多分辨率适配问题的目的是什么呢?根本目的当然是实现不同分辨率设备上用户体验的统一。换句话说,就是不同分辨率设备显示效果虽然可以不同,但显示的内容和样式是相同的。
我们先思考一下应该如何解决举例(1)中多分辨率适配问题导致的两款手机上同一图片显示的不一致。
很容易想到有三种思路:
思路1:使用不同的资源适配不同分辨率的设备。针对举例(1)就是再做一张640*960的图片,通过获取设备的分辨率使用相应分辨率的资源。这种方案仅适用于设备分辨率比较少的情况。如果设备分辨率很多,那么势必要针对每一种设备分辨率做一套资源,那将是游戏美工的噩梦。同时,发行时游戏资源包将变得异常大,如果采用分设备发行游戏资源包,维护和管理将变得极为困难。
思路2:使用同一资源通过资源缩放适配不同分辨率的设备。针对举例(1)就是在640*960屏幕分辨率下,将320*480的图片放大一倍后再显示。这种方案可能存在的两个问题:一是资源的分辨率比设备分辨率大,资源存在浪费;二是资源的分辨率比设备分辨率小,势必放大资源,影响显示效果。
思路3:结合方案1和方案2,使其在显示效果和资源使用率上达到平衡。
Cocos2D-x在cocos2d-2.0-x-2.0.4版本提供了多分辨率适配问题的解决方案,在这之前开发者只能自己想办法解决,而该解决方案其实就是以思路2作为依据的。
下面我们就来学习一下,Cocos2D-x是如何解决多分辨率适配问题。Cocos2D-x引入了几个全新的概念,需要理解这些概念的含义才能明白Cocos2D-x的解决方案。
·设计屏幕大小(designSize/winSize):也可以理解为逻辑屏幕大小。它是Cocos2D-x框架为开发者提供的标准界面,开发者只需要基于设定的设计屏幕大小进行开发,至于标准界面与不同设备之间的适配,则由Cocos2D-x框架实现。通过标准界面就达到了隐藏不同设备的差异,使游戏开发所有资源的映射都基于标准界面。
·实际屏幕大小(screenSize):它表示物理屏幕大小。实际上就是指不同设备的分辨率大小。Cocos2D-x框架需要获取该值,实现从设计屏幕大小到实际屏幕大小的适配。
·可视屏幕大小(visibleSize):它是建立在设计屏幕大小概念基础上的,表示能够显示的区域大小。它是设计屏幕大小的子集。
有了这些概念,就可以进一步理解Cocos2D-x的解决方案的原理。它通过获取实际屏幕大小和开发者设置的设计屏幕大小,就可以求出它们之间的比例;在渲染的时候,把资源按照这个比例来缩放绘制。
在求实际屏幕大小与设计屏幕大小的比例时,可能出现宽高比不同的情况。例如设计屏幕大小为480*320(宽高比=480/320=1.5),而实际屏幕大小为1024*788(宽高比=1024/768=1.3)。这时宽高比不同,资源也就无法缩放来填满屏幕。
Cocos2D-x定义了三种模式来处理宽高比不同的情况,在实际开发中开发者可以根据需要选择不同的模式:
·kResolutionExactFit模式:完成适应模式。通过拉伸资源的方式填满屏幕;也就是以宽比和高比作为缩放比例分别进行缩放,但这会使资源产生变形。如下图((红色线框指屏幕):
·kResolutionNoBorder模式:无边界模式。通过宽高等比缩放,但缩放比例取宽比和高比中最大的那个。这可以确保资源不变形缩放,但这会使有一部分资源超出屏幕。如下图(红色线框指屏幕):
·kResolutionShowAll模式: 全显示模式。通过宽高等比缩放,但缩放比例取宽比和高比中最小的那个。可以确保资源不变形缩放,但这会使资源无法填满屏幕。如下图(红色线框指屏幕):
不使用多分辨率适配,图片显示时将不会被压缩,由于图片的分辨率为960*640,而实际屏幕大小 为480*320,所以屏幕只能显示图片的一半。
我们再来看一看宽高比不同的情况下,多分辨率适配的三种模式的区别,如下:
条件设置1:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionExactFit);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionExactFit模式后,图片被拉伸显示。
条件设置2:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionNoBorder);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionNoBorder模式后,图片未变形,但图片超出了屏幕显示。
条件设置3:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionShowAll);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionShowAll模式后,图片未变形,但图片未能填满屏幕,两边有黑色空隙。
现在应该理解Cocos2D-x的多分辨率适配的三种模式吧。现在我们再来看HelloCpp中的下面一段代码:
bool HelloWorld::init()
{
...
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//可视屏幕大小
CCSize winSize = CCDirector::sharedDirector()->getWinSize();//设计屏幕大小
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); //可视屏幕原点...
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));//设置精灵位置为屏幕中心...
}
在条件设置1(kResolutionExactFit模式)中,运行结果如下:
visibleSize->(960,640)
winSize->(960,640)
origin->(0,0)
在条件设置2(kResolutionNoBorder模式)中,运行结果如下:
visibleSize->(960,300)
winSize->(960,640)
origin->(0,170)
在条件设置3(kResolutionShowAll模式)中,运行结果如下:
visibleSize->(960,640)
winSize->(960,640)
origin->(0,0)
可以看出,在kResolutionNoBorder模式下,当宽高比不同时,可视屏幕大小将小于设计屏幕大小。定义可视屏幕大小的目的就是因为在kResolutionNoBorder模式下,渲染绘制资源可能会超出屏幕显示。在设置精灵对象位置时使用可视屏幕大小而不是设计屏幕大小,可以确保在任何模式下都能够正确显示。
Cocos2D-x的多分辨率适配解决方案就讲到这里。我们可以认识到,其实Cocos2D-x提供的三种可选模式都存在着不同的缺陷,我在博客上曾经看到一篇文章,作者试图基于kResolutionNoBorder模式和kResolutionShowAll模式的特点提出新的适配解决方案。至于这个新解决方案已经超出了本内容的范围,有兴趣的同学可以自己去琢磨和研究。
----------------------------------------------------------------------------------------------------------------------------------------
注:本人在本博客的原创文章采用创作共用版权协议(http://creativecommons.org/licenses/by-nc-sa/2.5/cn/), 要求署名、非商业用途和保持一致。要求署名包含注明我的网名及文章来源(我的博客地址:http://www.cnblogs.com/binbingg)。