最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
Cocos与Cocos2d-x协作的完整教程:多分辨率支持
从Cocos v2.1开始,新增了一种多分辨率适配方案——流式布局。与CocosStudio v1.x时代相比,流式布局更为简单纯粹,没有许多复杂的概念,易于理解和上手。本教程将详细介绍如何使用这一功能,从Cocos编辑配置到与Cocos2d-x协作,提供完整的操作指南。
此前,我曾撰写过一篇布局教程,但反响不佳,不少读者在看完后仍有诸多疑问,尤其是与2d-x协作相关的问题。因此,本次我将提供一个更为详尽的版本。
目录
- Cocos编辑器配置部分
- Cocos2d-x(Cocos Framework)中的相关概念及代码设置
一、Cocos编辑器配置部分
这部分内容参考了手册(其实手册也是我编写的)。自动布局系统主要涉及固定与拉伸属性。
如图所示,总共可以修改控件的上下左右四个图钉和中间的两个拉伸条,共计六个属性。
效果
- 固定单边距离:当打开其中任意一个图钉时,当前节点与父节点对应边的距离将被固定。无论父节点的大小如何修改,当前节点与父节点对应边的距离始终保持不变。
- 固定相对边距离比例:当打开其中任意两个相对的图钉时,当前节点与父节点对应两边的距离将成固定比例。也就是说,当修改父节点的大小时,当前节点到父节点对应两条边的距离之比始终不变。
- 固定宽度或高度比例:当开启中间任意一条拉伸条,例如横向拉伸条,节点的宽度与父节点的宽度之比将固定不变。
其他情况
- 默认位置:若不开启上述任意属性,对象默认相对左下角位置不变。
- 拉伸条属性适用范围:当前仅控件对象(文本、FNT字体除外)和容器两种类型具有拉伸条属性。
根据上述描述,相信大部分读者已经能够掌握该功能的配置方法,因此这里不再赘述。接下来,我们将创建一个界面,并使用固定图钉和拉伸条将其中的控件固定在相应位置。除了“no set”按钮外,其他所有控件都进行了布局相关的设置。附件中包含该界面的工程和第二部分的代码(以下简称demo),大家可以自行打开查看。建议调整左上角的场景大小,观察布局效果。
二、Cocos2d-x(Cocos Framework)中的相关概念及代码设置
设计分辨率和屏幕分辨率
在Cocos2d-x中,存在两种分辨率:设备分辨率和设计分辨率。设备分辨率指的是当前游戏所运行平台的实际分辨率;设计分辨率则是我们设计游戏时所采用的分辨率。
设计分辨率是可以设置的,它是游戏程序能够“感知到”的分辨率大小。当界面超出该区域时,超出部分将不会显示。设计分辨率通常在游戏启动时进行设置,在demo中,相关设置在AppDelegate::applicationDidFinishLaunching中完成,代码如下:
director->getOpenGLView()->setDesignResolutionSize(960, 640, ResolutionPolicy::FIXED_HEIGHT);
(在桌面系统上,上述代码之前还有一句createWithRect,用于创建游戏模拟器。可以修改Rect的后两个值来调整设备分辨率,但该设置在移动设备上无效。)
那么,这句代码的含义是什么呢?它将设计分辨率设置为960x640,并将游戏界面调整方案设置为固定高度。然而,设置之后,后续获取设计分辨率时,得到的大小可能并非960x640。这是为什么呢?
让我们查看源码(侯捷大爷的名言“源码面前,了无秘密~”犹在耳边)。转到setDesignResolutionSize的定义处,会发现其中进行了一些判断和赋值操作,最终调用了updateDesignResolutionSize。继续查看updateDesignResolutionSize函数,部分代码如下:
// 1. 计算游戏界面在缩放至充满屏幕的情况下X、Y轴的缩放率:
_scaleX = (float)_screenSize.width / _designResolutionSize.width;
_scaleY = (float)_screenSize.height / _designResolutionSize.height;
// 2. 根据适配策略,调整缩放率和设计分辨率:
if (_resolutionPolicy == ResolutionPolicy::NO_BORDER) {
// 将X、Y轴缩放值设置为其中的最大者
_scaleX = _scaleY = MAX(_scaleX, _scaleY);
} else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL) {
// 将X、Y轴缩放值设置为其中的最小者
_scaleX = _scaleY = MIN(_scaleX, _scaleY);
} else if (_resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) {
// 将X、Y轴缩放值固定为Y轴缩放值,调整设计分辨率的宽度,使设计分辨率的宽度在缩放后依然能够充满屏幕。
_scaleX = _scaleY;
_designResolutionSize.width = ceilf(_screenSize.width / _scaleX);
} else if (_resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {
// 将X、Y轴缩放值固定为X轴缩放值,调整设计分辨率的高度,使设计分辨率的高度在缩放后依然能够充满屏幕。
_scaleY = _scaleX;
_designResolutionSize.height = ceilf(_screenSize.height / _scaleY);
}
// 其他缩放策略: EXACT_FIT不作调整
这段代码主要完成了两件事:
- 根据设备分辨率和设计分辨率计算游戏界面的缩放率。
- 调整设计分辨率。
根据上述源码,我们可以清晰地理解几种缩放策略的含义:
- NO_BORDER:在保持设计分辨率大小不变的情况下,将游戏界面按比例缩放至充满屏幕。此时,游戏的上下或者左右两边可能会被裁剪。
- SHOW_ALL(Cocos2d-x默认方案):在保持设计分辨率大小不变的情况下,将游戏界面按比例缩放至设计分辨率的其中一边顶住屏幕。游戏上下或者左右两边可能会出现黑边。
- FIXED_HEIGHT:固定设计分辨率的高度,调整设计分辨率的宽度,使设计分辨率的长宽比与设备分辨率的长宽比相同,然后缩放游戏界面至充满屏幕。
- FIXED_WIDTH:与
FIXED_HEIGHT类似,不同之处在于保持宽度不变,调整高度。 - EXACT_FIT:最为直接的方式,直接将游戏界面缩放到充满整个屏幕,X轴和Y轴的缩放比率不一定一致。
那么,我们应该选择哪种方案呢?建议选择FIXED_HEIGHT或者FIXED_WIDTH。因为只有这两种方案能够使界面根据设备分辨率自动调整设计分辨率的大小,并充满屏幕。
Demo示例
在demo中,我设置的是FIXED_HEIGHT。大家可以下载该demo,调整此值以及设计分辨率的大小,观察不同设置下的效果。
设置完成后,demo的游戏界面分辨率将自动根据手机的分辨率进行调整。接下来,我们将加载界面。在demo中,界面加载在HelloWorld::init中完成,代码如下:
auto rootNode = CSLoader::createNode("MainScene.csb");
auto size = Director::getInstance()->getVisibleSize();
rootNode->setContentSize(size);
ui::Helper::doLayout(rootNode);
addChild(rootNode);
除了使用createNode加载界面并将其添加到HelloWorld中,还进行了另外两件事:设置加载出来的界面的ContentSize,并调用ui::Helper::doLayout对加载出来的界面进行处理。
为什么不将这些操作设计为自动完成呢?这里有一个有趣的段子:我们的研发同学曾考虑在createNode中自动设置大小,但他犹豫了,担心加载出来的界面与开发者在编辑器中设置的不一致,会引发用户的不满,于是出去抽了根烟,回来后继续加班。
虽然这是个段子,但也说明了其中一个原因:与编辑器设置不一致。另外一个原因是,自动调整界面被设计为被动操作,若主动进行,可能会导致大量的性能损失。因为每次设置大小都需要重新遍历计算所有子节点的位置,会消耗大量的CPU时间。
效果展示
考虑到部分开发者可能比较“懒”,不愿意下载demo查看效果,下面为大家简单介绍几种情况的效果(描述较为简略,若不理解可查看代码):
- 设备分辨率X/Y相对设计分辨率X/Y较大,适配策略为固定高度。
- 设备分辨率X/Y相对设计分辨率X/Y较大,适配策略为固定宽度。
- 设备分辨率X/Y相对设计分辨率X/Y较小,适配策略为固定高度。
- 设备分辨率X/Y相对设计分辨率X/Y较小,适配策略为固定宽度。
DEMO下载
补充说明
枚举类型ResolutionPolicy是框架为我们提供的方便的默认方案。实际上,在设置设计分辨率之前,我们可以先获取设备分辨率,然后根据设备分辨率自行调整设计分辨率。