再谈cocos2d-x屏幕适配

一直以来,在 cocos2d-x 平台中如何用一套资源适配全屏幕都是每个程序的梦想。随手百度都可以搜索到很多关于 cocos2dx 适配的文章,但是看完之后的感觉仍然是不知道如何具体操作,所以自己参考网上其他人的帖子,并结合 cocos2dx 源码,自己验证了一番在此做个总结。如有不正确的地方请大家提出讨论。

首先是做 Android 的同学们先暂时忘掉 dpi 的概念,无论是几寸屏多少 dpi,在cocos2dx 里面只关心像素就可以了。

cocos2dx里面提供几种概念,FrameSize/WinSize/WinPixel/VisibleSize/VisibleOrigin,那么就一次性都输出出来看看这些值都是代表什么。

测试环境

iPhone6 (640x1136)

iPhone6 plus (1242x2208)

Nexus4 (768x1184)

在 iPhone6的模拟器上运行获得如下结果

cocos2d: FrameSize width = 640.000000  height = 1136.000000

cocos2d: WinSize width = 640.000000  height = 1136.000000

cocos2d: WinPixel width = 640.000000  height = 1136.000000

cocos2d: VisibleSize width = 640.000000  height = 1136.000000

cocos2d: VisibleOrigin x = 0.000000  y = 0.000000

在 Nexus4上输出结果如下


然后,我设置了一下

auto director = Director::getInstance();

auto glview = director->getOpenGLView();

glview->setDesignResolutionSize(1242.0f, 2208.0f, ResolutionPolicy::FIXED_HEIGHT);

再次输出上面那些值

cocos2d: frameSize width = 640.000000  height = 1136.000000

cocos2d: WinSize width = 1244.000000  height = 2208.000000

cocos2d: winPixel width = 1244.000000  height = 2208.000000

cocos2d: visibleSize width = 1244.000000  height = 2208.000000

cocos2d: visibleOrigin x = 0.000000  y = 0.000000


所以我们得出一个结论 FrameSize 是屏幕的真实尺寸,WinSize = WinPixel = VisibleSize, 受我们设置的 DesignResolutionSize影响。这里没有对 WinSize 及 VisibleSize 做更多的测试,通过设置可能会存在不一致的情况,这里先不对这些情况讨论。


接下来我们看一下 ResolutionPolicy::FIXED_HEIGHT 相关的设置。

找到源码:void GLView::updateDesignResolutionSize()函数

        _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);

        }


通过分析源码,得到如下结论:

ResolutionPolicy::EXACT_FIT--全屏,如果屏幕比例跟设计尺寸的比例不相等,则图片会被变形拉伸。

ResolutionPolicy::NO_BORDER--无黑边模式,如果屏幕比例跟设计尺寸的比例不相等,则一定有一个方向被裁剪。

ResolutionPolicy::SHOW_ALL--全屏模式,如果屏幕比例跟设计尺寸的比例不相等,则一定有一个方向显示黑边。

ResolutionPolicy::FIXED_HEIGHT--按高度适配,果屏幕比例跟设计尺寸的比例不相等,则横向要么被裁剪,要么出黑边。

ResolutionPolicy::FIXED_WIDTH--按宽度适配,果屏幕比例跟设计尺寸的比例不相等,则纵向要么被裁剪,要么出黑边。

以上都是废话,人家注释里写的清清楚楚。

说了这么多最想知道的问题还是没有得到解答,我该用哪个模式?设计分辨率应该设置多大?美术应该切多大的图?

下面根据我个人的理解,对这几个问题一一解答。

1,模式的选择。

如果能忍受黑边,推荐 SHOW_ALL模式。这样美术最省力,严格按照DesignResolutionSize画就可以了。

如果能忍受变形拉伸,就直接EXACT_FIT,但是我个人是不接受变形拉伸的。朋友之前的一款游戏采用这个模式,素材在设计的时候比例介于16:9跟4:3之间,所以拉伸的时候变形也不是很严重,大家可以参考。

如果你采用剩下的3种模式一定要提前跟美术沟通,因为可能会产生裁剪。

NO_BORDER模式由于不确定哪个方向产生裁剪,美术同学可能会疯掉。需要两个方向都预留出来一部分内容,即便被裁剪掉也不影响整体效果即可。

如果采用 FIEXD_HEIGHT模式,请美术同学在横向上预留出一部分内容以防被裁剪。

如果采用 FIEXD_WIDTH 模式,请美术同学在纵向上预留出一部分内容以防被裁剪。

2,DesignResolutionSize。

这个设计分辨率直接影响包的尺寸,所以要慎重。



苹果还是很良心的,6跟6p 的横纵比是相等的,所以只要DesignResolutionSize的横纵比是0.563,选任何上面一个模式都是全屏不变形无黑边无裁剪

这次提供的素材是1242x2208,显示到 Nexus4的时候两侧出现了黑边(setDesignResolutionSize(1242.0f2208.0fResolutionPolicy::FIXED_HEIGHT);)

原因是这个模式下 WinSize是1433,2208。

关于如何切图,

先根据游戏的类型及包尺寸的要求,决定适配模式。程序同学请事先同美术沟通好,再决定一个DesignResolutionSize,核心的元素需要画在这个尺寸之内。另外根据模式再在需要的方向上留一定的被裁剪空间。

FIXED_HEIGHT 模式素材提供的横纵比略大一些,两侧留一些被裁剪的空间,就可比较好的适配各种屏幕。setDesignResolutionSize 函数的第一个参数只要不为0即可,计算的时候会被无视掉。

FIXED_WIDTH 模式素材提供的横纵比略大一些,上下预留被裁剪的空间。setDesignResolutionSize 函数的第二个参数只要不为0即可,计算的时候会被无视掉。

SHOW_ALL最简单,美术不需要预留,严格按DesignResolutionSize切图,请容忍黑边。

NO_BORDER,美术两个方向都要预留被裁剪的空间。

EXACT_FIT,横纵比取折衷大小,容忍变形。

采用以上的方法之后,图片应该不需要在代码中二次缩放,因为 cocos2dx 已经替你进行缩放了。

那么程序还需要解决一个问题,界面元素与元素之间的距离。

FIXED_HEIGHT 模式下纵向位置固定为设置的 DesignResolutionSize,所以请美术直接给出高度就可以直接使用,不论上边距还是下边距不需要适配。但是横向上像素数量不固定,请以屏幕中轴做参考向两侧距离适配。FIXED_WIDTH 同理横向不需要特别适配,纵向以中轴做参考向两侧适配。

SHOW_ALL/NO_BORDER/EXACT_FIT 三个模式横向纵向最好都以中轴做参考适配。当然有些时候按钮跟背景图片位置不关联,这个时候只要保证不出屏幕就可以了。


由于时间关系没有进行更多机型的适配测试,难免有遗漏或者错误的地方,欢迎大家把自己实际测试的情况也分享下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值