一、基础概念
五种适配模式: @H_502_7@
EXACT_FIT:会靠拉伸来填满屏幕,背景图会变形来充满屏幕,因为1024:768=1.3, 480:320=1.5,宽高比不同,图片也就无法等比缩放来填满屏幕,只能变形了。@H_502_7@
NO_BORDER:看不到黑边,实际就是宽高等比缩放,但缩放比例取宽比和高比中大的那一个@H_502_7@
- SHOW_ALL:全部显示,可以理解为保证内容都显示在屏幕之内,实际也是宽高等比缩放,但缩放比例取宽比和高比之中小的那一个。
- FIXED_HEIGHT:保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。
- FIXED_WIDTH:保持传入的设计分辨率宽度不变,根据屏幕分辨率修正设计分辨率的高度。
两种分辨率:@H_502_7@
- 窗口分辨率:在电脑上就是显示窗口的分辨率,在手机上就是手机的屏幕分辨率
- 设计分辨率:游戏在设计时候的分辨率,也就是可视区域的大小
适配原理: @H_502_7@
就是根据不同的适配模式,设计分辨率,窗口分辨率生成最终可视区域大小的转换过程。
二、代码相关—CCGLView
在不同平台下,CCEGLView是不同的
(PS:cocos2d-x中有很多这样的用法,即同一个头文件,在不同平台上实现不同)
CCEGLView除了和屏幕适配有关外,还用来处理鼠标点击模拟器触摸,按键等事件的处理。
设置窗口大小:@H_502_7@
void GLView::setFrameSize(float width,float height) { _designResolutionSize = _screenSize = Size(width,height); }
设置设计分辨率大小和适配模式:@H_502_7@
void GLView::setDesignResolutionSize(float width,float height,ResolutionPolicy resolutionPolicy) { CCASSERT(resolutionPolicy != ResolutionPolicy::UNKNOWN,"should set resolutionPolicy"); if (width == 0.0f || height == 0.0f) { return; } _designResolutionSize.setSize(width,height); _resolutionPolicy = resolutionPolicy; updateDesignResolutionSize(); }
根据设计分辨率、窗口分辨率大小和适配模式生成可视区域的大小:@H_502_7@
void GLView::updateDesignResolutionSize() { if (_screenSize.width > 0 && _screenSize.height > 0 && _designResolutionSize.width > 0 && _designResolutionSize.height > 0) { //获取宽高比 _scaleX = (float)_screenSize.width / _designResolutionSize.width; _scaleY = (float)_screenSize.height / _designResolutionSize.height; //没有黑边,取宽高比大的那个 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); } //计算生成可视区域的宽高 // calculate the rect of viewport float viewPortW = _designResolutionSize.width * _scaleX; float viewPortH = _designResolutionSize.height * _scaleY; _viewPortRect.setRect((_screenSize.width - viewPortW) / 2,(_screenSize.height - viewPortH) / 2,viewPortW,viewPortH); // reset director's member variables to fit visible rect auto director = Director::getInstance(); director->_winSizeInPoints = getDesignResolutionSize(); director->_isStatusLabelUpdated = true; director->setGLDefaultValues(); } }
在上面的代码中我们可以看到最终的大小被定义在_viewPortRect这个矩形中,然后我们全局搜索这个变量:@H_502_7@
void GLView::setViewPortInPoints(float x,float y,float w,float h) { /**glViewport是OpenGL中的一个函数。在默认情况下,视口被设置为占据打开窗口的整个像素矩形,为了选择一个更小的绘图区域, 就可以用glViewport函数来实现这一变换,在窗口中定义一个像素矩形,最终将图像映射到这个矩形中。 例如可以对窗口区域进行划分,在同一个窗口中显示分割屏幕的效果,以显示多个视图。(我第一眼就想到了超市的监视系统)**/ glViewport((GLint)(x * _scaleX + _viewPortRect.origin.x),(GLint)(y * _scaleY + _viewPortRect.origin.y),(GLsizei)(w * _scaleX),(GLsizei)(h * _scaleY)); }
三、实例详解
因为我一直在做卡牌游戏相关的研发,所以举个卡牌游戏适配模式的采用方式。一个是卡牌游戏发展史的前期像刀塔传奇这样所采用的黑边模式,一个是卡牌游戏发展史的近期像比较火的火影、98拳皇之类的无黑边模式。@H_502_7@
(1)刀塔传奇类黑边:
@H_502_7@
设计分辨率:960x640
适配模式: SHOW_ALL
背景图:1200x640
UI布局:一定要采用相对布局@H_502_7@
在项目工程的根目录下有个config.json
文件,在这个文件里有主流的屏幕分辨率:@H_502_7@
"simulator_screen_size": [ { "title": "iPhone 3Gs (480x320)","width": 480,"height": 320 },{ "title": "iPhone 4 (960x640)","width": 960,"height": 640 },{ "title": "iPhone 5 (1136x640)","width": 1136,{ "title": "iPad (1024x768)","width": 1024,"height": 768 },{ "title": "iPad Retina (2048x1536)","width": 2048,"height": 1536 },{ "title": "Android (800x480)","width": 800,"height": 480 },{ "title": "Android (854x480)","width": 854,{ "title": "Android (1280x720)","width": 1280,"height": 720 },{ "title": "Android (1920x1080)","width": 1920,"height": 1080 }
iPhone 3Gs
:按比例适配,完美适配
iPhone 4
:按比例适配,完美适配
iPhone 5
:高度完美适配,宽度裁剪,因为UI布局采用的是相对布局,背景图采用的是iPhone 5的背景图,所以显示出来的效果也是无黑边
iPad (1024x768)
:宽度适配,高度出现黑边 @H_502_7@
768/640 = 1.2 宽度缩放 1024/960 = 1.06666 高度缩放 因为是SHOW_ALL模式,所以缩放比例取比例小的那个,这里取1.06666 640 * 1.06666 = 682 因为682 < 768,所以高度出现黑边
iPad Retina (2048x1536)
:同iPad (1024x768)一样,大小正好是2倍
Android (800x480)
:@H_502_7@
800/960 = 10/12 = 5/6 宽度缩放 480/640 = 6/8 = 3/4 高度缩放 因为是SHOW_ALL模式,所以缩放比例取比例小的那个,这里取3/4 960 * 3/4 = 720 1200 * 3/4 = 900 宽度最终显示大小为720,因为我们的屏幕分辨率宽度为800,800>720,800<900,所以最终的显示为高度完美适配,宽度部分裁剪
Android (854x480)
:同Android (800x480)
Android (1280x720)
:@H_502_7@
1280/960 = 1.3333 720/640 = 1.125 取缩放比例小的那个,这里取1.125 960*1.125 = 1080 1200*1.125 = 1350 1280>1080,1280<1350,所以最终显示为宽度部分裁剪
(2)98拳皇类无黑边:@H_502_7@
设计分辨率:850x640
适配模式: FIXED_HEIGHT
背景图:1200x640
UI布局:一定要采用相对布局 @H_502_7@
这里详细讲解一下设计分辨率为什么采用850?
在所有的主流分辨率里,iPad (1024x768)
是高比宽比例最大的,我们让高度固定后,也就是说,相同的高度,宽度最小的,采用这个分辨率后,所有的屏幕都能完美适配,所以我们按比例缩放,高度变成640后,宽度变成850,这样就再也不会出现黑边了。@H_502_7@