cocos-js,屏幕适配

一、基础概念

五种适配模式:

  • EXACT_FIT:会靠拉伸来填满屏幕,背景图会变形来充满屏幕,因为1024:768=1.3, 480:320=1.5,宽高比不同,图片也就无法等比缩放来填满屏幕,只能变形了。

  • NO_BORDER:看不到黑边,实际就是宽高等比缩放,但缩放比例取宽比和高比中大的那一个

  • SHOW_ALL:全部显示,可以理解为保证内容显示在屏幕之内,实际也是宽高等比缩放,但缩放比例取宽比和高比之中小的那一个
  • FIXED_HEIGHT:保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。
  • FIXED_WIDTH:保持传入的设计分辨率宽度不变,根据屏幕分辨率修正设计分辨率的高度。

两种分辨率:

  • 窗口分辨率:在电脑上就是显示窗口的分辨率,在手机上就是手机的屏幕分辨率
  • 设计分辨率:游戏在设计时候的分辨率,也就是可视区域的大小

适配原理:

就是根据不同的适配模式,设计分辨率,窗口分辨率生成最终可视区域大小的转换过程。

二、代码相关—CCGLView

在不同平台下,CCEGLView是不同的
(PS:cocos2d-x中有很多这样的用法,即同一个文件,在不同平台上实现不同)
CCEGLView除了和屏幕适配有关外,还用来处理鼠标点击模拟器触摸,按键等事件的处理。
设置窗口大小:

void GLView::setFrameSize(float width,float height)
{
    _designResolutionSize = _screenSize = Size(width,height);
}

设置设计分辨率大小和适配模式:

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();
 }

根据设计分辨率、窗口分辨率大小和适配模式生成可视区域的大小:

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这个矩形中,然后我们全局搜索这个变量:

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拳皇之类的无黑边模式。

(1)刀塔传奇类黑边:

设计分辨率:960x640
适配模式: SHOW_ALL
背景图:1200x640
UI布局:一定要采用相对布局

在项目工程的根目录下有个config.json文件在这文件里有主流的屏幕分辨率:

"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):宽度适配,高度出现黑边

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):

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):

1280/960 = 1.3333
720/640 = 1.125
取缩放比例小的那个,这里取1.125
960*1.125 = 1080
1200*1.125 = 1350
1280>1080,1280<1350,所以最终显示为宽度部分裁剪

(2)98拳皇类无黑边:

设计分辨率:850x640
适配模式: FIXED_HEIGHT
背景图:1200x640
UI布局:一定要采用相对布局

这里详细讲解一下设计分辨率为什么采用850?
在所有的主流分辨率里,iPad (1024x768)是高比宽比例最大的,我们让高度固定后,也就是说,相同的高度,宽度最小的,采用这个分辨率后,所有的屏幕都能完美适配,所以我们按比例缩放,高度变成640后,宽度变成850,这样就再也不会出现黑边了。

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...