由于各种智能手机的屏幕大小都不一致,会出现同一张图片资源在不同的设备分辨率下显示不一样的问题。为避免这样的情况,需要Cocos引擎能提供多分辨率的支持,也就是说要求实现这样的效果 — 开发者不需要考虑程序实际运行在什么分辨率下而只需要制定设置好设计分辨率就行,接着引擎便会自动实现设计分辨率(DesignSize)到屏幕分辨率(FrameSize)的转化,以及不同资源分辨率到设计分辨率的转化。
1.在适配过程中必须明确几个概念:
①Frame大小:这个值在windows/mac/linux下就是创建窗体的大小,在手机上就是屏幕大小。
设置方式:这里我们设置一个全局的变量(这个是iphone5/5s的分辨率)。
static cocos2d::Size g_frame_size = cocos2d::Size(1136, 640);
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
if(!glview) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
glview = GLViewImpl::createWithRect("ScreenFix", Rect(0, 0, g_frame_size.width, g_frame_size.height)); //这里设置窗体大小
#else
glview = GLViewImpl::create("ScreenFix"); //这里就是手机屏幕大小
#endif
director->setOpenGLView(glview);
}
获取方式:
Size cur_frame_size = Director::getInstance()->getOpenGLView()->getFrameSize();
②Design分辨率大小:逻辑设计分辨率大小,美术可以根据这个设计分辨率来设计资源大小以及UI布局。会根据不同的分辨率适配策略,按Frame和Design的某种比例进行缩放。
设置方式:这里我们设置一个全局的变量(这个是比较常用的分辨率),后面将不断修改分辨率策略对画面整体的影响。
static cocos2d::Size g_design_resolution_size = cocos2d::Size(960, 640);
glview->setDesignResolutionSize(g_design_resolution_size.width, g_design_resolution_size.height, ResolutionPolicy::EXACT_FIT); //这里设置分辨率策略
获取方式:(注意:修改分辨率策略,获得的设计分辨率将不一样!!!)
Size cur_design_size = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();
③VisibleSize:可视区域大小,一般情况下UI都要在可视范围内,根据这个值可以对UI进行位置的适配。
获取方式:
Size cur_visible_size = Director::getInstance()->getOpenGLView()->getVisibleSize();
④VisibleOrigin:可视区域原点位置,用于可视区域位置的计算。
获取方式:
Vec2 cur_origin = Director::getInstance()->getOpenGLView()->getVisibleOrigin();
一 设计分辨率
顾名思义,指由开发者自定义的分辨率,最终引擎会拿实际的屏幕分辨率和这个自定义的设计分辨率得到缩放因子。但实际的项目开发中还有细节要兼顾,如是否需要宽高都等比缩放,故有一知识点—缩放策略。在cocos2dx中通过setDesignResolutionSize来设置,方法使用如下:
setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);
参数width和height指定设计分辨率的尺寸,resolutionPolicy指定缩放策略,由ResolutionPolicy枚举定义,如下图所示:
//Cocos2dConstants.lua
cc.ResolutionPolicy =
{
EXACT_FIT = 0,
NO_BORDER = 1,
SHOW_ALL = 2,
FIXED_HEIGHT = 3,
FIXED_WIDTH = 4,
UNKNOWN = 5,
}
- ①EXACT_FIT :充满整个屏幕,唯一一个不按等比缩放的策略,宽高比不相等可能导致拉伸或压缩发生形变,一般情况下不使用;
- ②NO_BORDER :充满屏幕,等比缩放,实质上是屏幕宽、高分别和设计分辨率宽、高计算缩放因子,取较(大)者作为宽、高的缩放因子。保证了设计区域总能一个方向上铺满屏幕,而另一个方向一般会超出屏幕区域。 而区域是被居中对齐到屏幕(如上图);
- ③SHOW_ALL:保持全部元素可见,等比缩放。实质是屏幕宽、高分别和设计分辨率宽、高计算缩放因子,取较(小)者作为宽、高的缩放因子。保证了设计区域全部显示到屏幕上,但可能会有黑边(如上图)。
- 以上三者都不需要开发者对元素的位置进行调整,都是优先字面上的意思,NO_BORDER是“没黑边,但可能有裁剪”,SHOW_ALL是“完全没裁剪,但可能有黑边”,可以说两者刚好是相反的情况。
- ③FIXED_HEIGHT:也是等比缩放,按照 窗体(手机)分辨率高度/设计分辨率高度 的比例,缩放设计分辨率画面。这种设计分辨率,适合于横版游戏。美术出底图资源时,要保证宽度足够,否则会穿帮。它使用屏幕左下角作为原点。
- ④FIXED_WIDTH:也是等比缩放,按照 窗体(手机)分辨率宽度/设计分辨率宽度 的比例,缩放设计分辨率画面。这种设计分辨率,适合于竖版游戏。美术出底图资源时,要保证高度足够,否则会穿帮。它使用屏幕左下角作为原点。
二 调整元素位置
除了FIXED_XXXX,其他的缩放策略的绘制区域都是设计分辨率表示的有效区域,都是设计分辨率对应区域的原点。但是FIXED_XXXX对应的区域改变了,则程序中设定的绝对坐标往往失效,如下图的在一个分辨率中位于中点的点(100,50),在另一分辨率下就不再是中点了:
故针对使用FIXED_XXXX缩放策略的项目,开发过程中尽量不要使用绝对坐标,除此以外别的策略都没有问题。解决这个问题的方法是不固定边方向的坐标不要用绝对坐标,可以通过引入visibleSize辅助调整,如auto p2 = Vec2(visibleSize.width/2 - 10,visibleSize.height/2 + 3),这样便可实现逻辑对齐的自适应了。
三 视口设置
ViewPort的设置在OpenGL的GPU渲染管线中的屏幕映射占重要作用,在Cocos2dx中通过setViewPortInPoints方法来设置视口的大小:
void Director::setViewport()
{
if (_openGLView)
{
_openGLView->setViewPortInPoints(0, 0, _winSizeInPoints.width, _winSizeInPoints.height);
}
}
//CCGLView.cpp
void GLView::setViewPortInPoints(float x , float y , float w , float h)
{
glViewport((GLint)(x * _scaleX + _viewPortRect.origin.x),
(GLint)(y * _scaleY + _viewPortRect.origin.y),
(GLsizei)(w * _scaleX),
(GLsizei)(h * _scaleY));
}
setViewPortInPoints方法将基于设计分辨率的坐标信息转换为基于屏幕实际像素大小的坐标信息,然后使用GL指令glViewPort进行设置。