cocos2d-x屏幕 适配
发布日期:2021-06-28 22:16:04 浏览次数:2 分类:技术文章

本文共 8584 字,大约阅读时间需要 28 分钟。

// initialize director

Director* pDirector = Director::getInstance();

EGLView* pEGLView = EGLView::getInstance();

pDirector->setOpenGLView(pEGLView);

Size win_size=pDirector->getWinSize();//屏幕尺寸

int w=win_size.width;

int h=win_size.height;

    

int design_w=1280;

int design_h=720;

float s=w/(float)h;

float scale_w=w/(float)design_w;//宽度缩放比例

float scale_h=h/(float)design_h;//高度缩放比例

float scale=1;

//做分支处理(以宽度做为判断依据)

if(w>design_w){

//屏幕尺寸比设计尺寸大,需要做放大处理

if(scale_w>scale_h){

//宽度放大比例大于高度放大比例 先确定比例小的尺寸 即高度

design_h=720;

design_w=(int)(design_h/s);

}else{

//宽度放大比例小于高度放大比例,先确定比例小的尺寸,即宽度

design_w=1280;

design_h=(int)(design_w/s);

}

}elseif(w<design_w){

//屏幕尺寸比设计尺寸小,需要做缩小处理

if(scale_w<scale_h){

//宽度放大比例大于高度放大比例 先确定比例小的尺寸 即高度

design_w=1280;

design_h=(int)(design_w/s);

}else{

//宽度放大比例小于高度放大比例,先确定比例小的尺寸,即宽度

design_h=720;

design_w=(int)(design_h*s);

}

}else{

design_w=1280;

design_h=(int)(design_w/s);

}

    //按照这个尺寸 达到 全屏显示

pEGLView->setDesignResolutionSize(design_w, design_h, ResolutionPolicy::SHOW_ALL);

参考:

====本教程基于cocos2d-x-2.1.4撰写====

1. setDesignResolutionSize使用方法及主要的三种适配模式

在cocos2d-x 2.0里,提供了一个叫做setDesignResolutionSize的方法,直接一次设置就可以自动适配各种分辨率。这个方法的注释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum ResolutionPolicy
{
kResolutionExactFit,
kResolutionNoBorder,
kResolutionShowAll,
kResolutionFixedHeight,
kResolutionFixedWidth,
kResolutionUnKnown,
};
/**
* Set the design resolution size.
* @param width Design resolution width.
* @param height Design resolution height.
* @param resolutionPolicy The resolution policy desired, you may choose:
*                         [1] kResolutionExactFit Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
*                         [2] kResolutionNoBorder Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
*                         [3] kResolutionShowAll  Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
*/
virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);

这个方法的使用很简单,在游戏启动过程的 pDirector->setOpenGLView(pEGLView); 行之后,直接调用一次就好。调用完了之后,CCDirector->WinSize就会变更为你设定的分辨率,之后就按照这个WinSize进行开发就好了,当然有些时候还是需要一些注意一些额外的地方后面会提到。

这个方法的作用简单来说,就是我们可以只按照一套指定的分辨率设计游戏,称之为design resolution。然后选择合适的适配方案,引擎就会在你的design resolution的基础上进行缩放操作,使得按照指定分辨率设计的游戏可以适配各种分辨率。

具体的主要适配方案主要有以下三种,为了方便理解还会配图说明,先举一个例子:

这是我们的实际屏幕尺寸,有宽屏568×320和正屏480×360两种:

而这是我们设定的design resolution 480×320:

1) kResolutionExactFit:强制拉伸游戏方案,这个方案实用性很低,用暴力的拉伸直接将游戏拉伸到全屏,会导致图片比例失真

2) kResolutionNoBorder:无黑边保持高宽比拉伸方案,这个方案最美观,但是等比拉伸会导致左右或上下总会有一部分显示到屏幕外,需要自己去保证UI元素不会显示在屏幕外

(可以看到如果我们按照design resolution直接设计UI,贴在上下两侧的按钮等就可能显示到屏幕外了。但是实际上cocos2d-x有提供方案来帮助帮助我们保证UI元素绘制在屏幕内,后面的内容会提到具体方法。)

3) kResolutionShowAll:有黑边保持宽高比全显示拉伸方案,这个方案在在上两种方案之间,保持了宽高比也显示了全部内容,但是会在屏幕两侧留下黑边

(可以看到design resolution和实际屏幕宽高比相差太大的话黑边会比较多,但是这个方案是设计时最省心的)

三种适配模式都讲解完了,大家对选用哪种模式应该自己心里也都有数了。实际上最省心的方案就是找一个宽高比居中的design resolution,然后如果选用方案2的话就额外注意把元素都不要摆的太靠边就OK了。

不过这样做出来的游戏显得对用户体验太不上心了,个人觉得至少要检测一下屏幕的实际宽高比,对宽屏和正屏系列采用两套以上分辨率才可以。确定最合适的分辨率需要事先考察一下主流的屏幕分辨率,这里为了方便把分辨率统一转换成宽高比方便比较:

(安卓设备分辨率来自)
iPad: 1.333 : 1
iPhone5: 1.775 : 1
iPhone4(s): 1.5 : 1
WVGA800(800×480): 1.667 : 1
WVGA854(854×480): 1.779 : 1
1024×600: 1.707 : 1
WXGA(1280×800): 1.6 : 1
1024×768: 1.333 : 1
1280×768: 1.667 : 1
综上观察手持设备的分辨率再多,大部分也都遵循了显示器界4:3、16:9、16:10三大主流宽高比,iPhone4(s)算是略特殊的一个宽高比。基于这个统计,再根据游戏主推的平台,就可以确定两到三个主支持分辨率来进行设计了。当然,根据高清设备采用一个高清的分辨率方案,有时也是很必要的。

2. 关于getVisibleSize和getVisibleOrigin

针对上文中kResolutionNoBorder模式下,游戏UI有可能绘制到屏幕外的问题,有没有什么好的处理办法?答案是有,cocos2d-x为我们准备了方法来获取真正的可视范围,详情见这两个方法:

1
2
3
4
5
6
7
8
9
/**
* Get the visible area size of opengl viewport.
*/
virtual CCSize getVisibleSize() const;
/**
* Get the visible origin point of opengl viewport.
*/
virtual CCPoint getVisibleOrigin() const;

拿设计分辨率480×360但实际屏幕为480×320举例(取这个值是因为没拉伸好计算 -__-!),这个时候画面上下会有一部分显示不出来,经过引擎的计算会得到如下的值:

visibleSize: 480 x 320
visibleOrigin: 0, 20

通过这两个值,我们就可以正确的取得视图上真正显示在屏幕内的矩形范围了。在这个值的配合下,将所有的UI元素指定为左上、左中、左下、中上、中下、右上、右中、右下8种对齐方式的一种,就可以动态的计算坐标,放在屏幕的合适位置了。

====水平有限,如有错误欢迎指正====

3. 动态变化的设计分辨率

上述的三种主要适配方案都是使用固定的设计分辨率的,比较方便设计师直接出固定坐标的UI设计图。

仔细看了看适配方案的枚举,可以看到还有两个方案在setDesignResolutionSize的注释里没有出现,他们就是kResolutionFixedHeight和kResolutionFixedWidth。(老实说没有研究代码前我也不知道这俩方案cocos2d-x已经出官方支持了,我和我的小伙伴们之前都是自己手动实现的啊 QAQ)

1) kResolutionFixedHeight:固定高度,动态宽度的适配模式,可以自由的自己根据动态的宽度处理游戏

2) kResolutionFixedWidth:固定宽度,动态高度的适配模式,可以自由的自己根据动态的高度处理游戏

这里拿固定高度方案来举个例子说明,比如我设定了固定高度600,如果屏幕实际高宽比为1.5 : 1,那么CCDirector->WinSize就会变成900×600;如果屏幕实际高宽比为1.667 : 1,那么CCDirector->WinSize就会变成1000×600。

看明白了没有?对!就是说固定高度的话,设计游戏全景的时候就要按最长的宽度可能(以600来算应该是600×1.78=1068)来设计,来保证最长宽高比的情况下右侧不会出现黑边。右侧的UI元素必须设定为“右对齐”,这样在宽度变窄的情况下UI元素会自动左移,宽度变宽的情况下UI元素会自动右移。另外要注意左右UI的摆放要保证在宽度最窄的情况下(600×1.333=800)不会重叠。

固定宽度的情况类似不多说了。

这是目前来说最好的动态适配方案,不用担心黑边也不用担心UI出屏幕。而且不用考虑复杂的8种对齐方式,因为宽度和高度有一个是固定的,所以只需要考虑两种对齐。对于横版或者竖版的卷轴游戏来说,这个适配方案需要的额外设计成本几乎为零。

从Cocos2d-x 2.0.4开始,Cocos2d-x提出了自己的多分辨率支持方案,废弃了之前的retina相关设置接口,提出了design resolution概念。
有以下相关接口:
CCEGLView::sharedOpenGLView()->setDesignResolutionSize() //设计分辨率大小及模式  
CCDirector::sharedDirector()->setContentScaleFactor() //内容缩放因子 
CCFileUtils::sharedFileUtils()->setResourceDirectory() //deprecated 
CCFileUtils::sharedFileUtils()->setSearchPaths() //资源搜索路径 
CCEGLView::sharedOpenGLView()->getFrameSize() //屏幕分辨率 
CCDirector::sharedDirector()->getWinSize() //设计分辨率 
CCDirector::sharedDirector()->getVisibleSize() //设计分辨率可视区域大小 
CCDirector::sharedDirector()->getVisibleOrigin() //设计分辨率可视区域起点 
从cocos2d-2.1beta3-x-2.1.1开始,
CCFileUtils::sharedFileUtils()->setResourceDirectory()
被新接口
CCFileUtils::sharedFileUtils()->setSearchPaths(searchPath)
替代
 
从Cocos2d-x 2.1.3开始,新加入了两种ResolutionPolicy(kResolutionFixedHeight, kResolutionFixedWidth),共5中模式。
 
官方分别在Multi_resolution_support 和 Mechanism_of_loading_resources有介绍。
 
本文从引擎使用者角度分析Cocos2d-x的多分辨率适配技术。
 
从Retina 到 design resolution
在Cocos2d-x 2.0.4之前,有Retina的概念,这个是从cocos2d-iphone过来的概念。
 
cocos2d-iphone为了支持Retina iphone 设备,使用了-hd等后缀来区分iphone和Retine iphone的图片资源。在设计游戏的时候,使用point 坐标系,而非真正的pixel坐标系。这点和iOS native应用开发提出的point概念一至,不用修改代码,就能在640×960的设备上跑之前320×480的程序,只是图片会看起来模糊,一旦加入@2x的图片,iOS自动加载@2x的图片,实现对Retna iphone的支持。
 
point坐标系,在一定范围内能解决多分辨率支持的问题。但是当iphone5,ipad 3出来以后,iOS总共有5个分辨率需要支持,如果做一个universal的程序,是相当痛苦的。point坐标系并不能完全解决问题,android上的分辨率情况更加复杂。
 
design resolution应该是从point坐标系进化过来的概念,目的是屏蔽设备分辨率,精灵坐标都在design resolution上布局,但要实现这个目标并不简单。Cocos2d-x提供了一组相关的接口和5种分辨率适配策略,哪种策略才是我们需要的,下面我们一同探寻。
具体参考:
http://www.cocoachina.com/applenews/devnews/2013/0809/6767.html
cocos2d-x添加了一个新的方法,可以非常简便地让cocos2d根据屏幕尺寸的大小做自适配。
方法名:
virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);
该方法所传的参数中,前两个参数width、height,指的是开发者在设计界面时默认设计的尺寸。例如:开发者在设计界面时以iphone5为准,则width和height就是568*320;若是以iphone4为准,则width和height就是480*320;以此类推。
第三个参数resolutionPolicy指的是cocos2d在缩放时需要遵守的规则。ResolutionPolicy这个自定义结构如下:
kResolutionExactFit是指cocos2d缩放的时候不考虑画面失真,直接用画面填充满整个屏幕
kResolutionNoBorder是指cocos2d缩放的时候尽量顶满画面,如果因此有超出画面的部分,就会把超出的部分切除掉(举例来说:如果设计大小是568*320,在480*320大小的屏幕上自适配的时候,就会把宽度超出的部分切除)
kResolutionShowAll是指cocos2d缩放的时候显示所有的画面,如果有填不满屏幕的地方就会显示黑条。
这三种规则各有优缺点,具体使用哪种规则需要考量项目的需要进行合理的选择。
 
然而,需要特别注意的一点是:setDesignResolutionSize和enableRetina这两个方法是不可以同时使用的。这即意味着使用自适配的时候是不可以做高清版的。
如果查看cocos2d-x源代码,可以看到在setDesignResolutionSize方法中有一句代码:
CCAssert(m_bIsRetinaEnabled == false, "can not enable retina while set design resolution size!");
在下认为这是因为高清模式下图片资源都是进行了缩小的,所有的坐标都是定义的point,而不是pixel。因此高清模式和自适配可能有某些冲突存在。(以上只是笔者的猜测,不靠谱勿怪)
 
 
总之,如果想要使用自适配,就必须在项目一开始就放弃高清。如果要做高清版,目前看来就只能自己根据屏幕尺寸的比例变化设置setContentScaleFactor,这一部分的设置方法这里就不展开了。
另外,笔者在刚开始使用自适配功能时,误以为开发时要把UI元素的位置坐标和大小都写成相对于屏幕大小的一定比例。例如:
CCSprite* avatarSprite = CCSprite::create("avatar.png"); avatarSprite->setPosition(ccp(winSize.width * 0.000878, winSize.height * 0.653125)); addChild(avatarSprite);
但实际上这是没有必要的。自适配功能是直接调整整个CCDirector的画布大小,因此任何添加到CCDirector中的元素都会被缩放相应的比例,没有必要再特意将坐标写成相对屏幕比例的模式。
具体参考:
http://www.cnblogs.com/eagley/archive/2013/05/31/3110785.html

转载地址:https://blog.csdn.net/yhhwatl/article/details/20948695 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:本地化处理 轻松支持多国语言
下一篇:IOS 设计模式

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月28日 18时30分37秒