cocostudio做出来的界面如何进行分辨率适配,兼论cocos2dx3的多分辨率适配机制,以及retina适配机制

时间:2023-03-09 14:16:41
cocostudio做出来的界面如何进行分辨率适配,兼论cocos2dx3的多分辨率适配机制,以及retina适配机制

cocos有很多代码实际上都不再使用了,看代码时反而误导了程序员。

比如一个简单的分辨率适配,我查到了setContentSize,然后调用setContentSize,毫无用处啊!于是乎,我到处查资料,终于发现解决办法,非常简单,纪录在下面。

做界面时,使用固定的设计分辨率,需要某个元素适配分辨率时,使用右边的锚点设置。做好以后载入进来,如此调用:

  Node* uiNode = CSLoader::getInstance()->createNode("file.csb");

    Size size(width, height);   //你要的屏幕分辨率

    uiNode->setContentSize(size);

    ui::Helper::doLayout(uiNode);

这样,布局就根据分辨率自动适配啦。

cocos中的Director还有一个contentScaleFactor的概念,这个怎么理解呢?从名字上看很有迷惑性,会让人觉得这个也是做分辨率适配的,事实上它和designedResolution是两套不干涉的系统。从代码里可以看出,设置投影矩阵时使用的是winSize,而winSize来自designedResolution。同时设置Viewport时用的也是winSize。

我们三维投影有两个阶段:世界坐标系->摄像机坐标系,摄像机坐标系->投影坐标系(z值发生变化,并进行了透视矫正),投影坐标系->屏幕坐标系。对2d渲染来说,摄像机坐标系直接被跳过,投影矩阵完成了第一第二步,cocos在这里用的就是winSize,将winSize范围内(其实也就是designedResolution,代码为证,见Director::setOpenGLView。因此,这意味着designedResolution大小范围内的几何体被变换到标准投影空间[-0.5, 0.5]。 第三步到屏幕坐标系的转换,使用的也是winSize;只不过这时,会将winSize乘以在setDesignedResolution时被纪录的scale得到一个和屏幕大小相匹配的大小,也就是说如果设计宽高和屏幕宽高不匹配,则在这一步以glViewPort的形式被缩放成匹配的(这时Viewport可能超过屏幕,比如你选择了NOBORDER,而宽高比又不相同)。这里scale并没有考虑retina缩放系数,因此对于Retina的ipad,这里的屏幕分辨率依然是1024x768。因此viewportimp中还乘以了一个retinafactor,把它变成2048x1536。

上面讨论了cocos的分辨率适配机制,可以看出,这个Director的contentScaleFactor压根就没有用到,因此它不影响三维渲染过程。

那么它影响的是什么呢?答案是它影响了每个面片的大小。cocos如何产生多边形?用sprite为例,它得到texture的size,然后就以这个size作为sprite多边形的宽高:注意,这个机制就是为什么要有contentScalefactor的根本原因,而以此出发,很容易明白为什么三维游戏不需要这个东西。此时的size其单位是逻辑坐标,不包含retinascale的,也就是说在retina显示器中依然用的是逻辑坐标1024x768(对ipad)。这时就有一个问题了,对retina显示器而言,同是逻辑大小50*50的区域,它有100*100个点,因此为什么不直接用100*100的图片呢?不行!因为前面所述,cocos生成多边形依赖了资源大小,此时会产生逻辑大小100x100的片,占用200x200的屏幕点。

于是Director的contentScaleFactor就闪亮登场了。它在所有取资源大小的地方都加入,作为乘数缩放了资源大小到我们的逻辑大小。如果你是两倍大小的retina资源,只需要设置contentScaleFactor为2,它们在载入的时候会生成一半大小的面片,从而符合了游戏设计分辨率。