Cocos2d-x——Cocos2d-x 屏幕适配新解 – 兼容与扩展【转载】

Cocos2d-x 屏幕适配新解 – 兼容与扩展

本文出自[无间落叶](转载请保留出处):http://blog.leafsoar.com/archives/2013/05-13-08.htmlhtml

在读这篇文章以前,先读前一篇文章 Cocos2d-x 屏幕适配新解 (http://www.ityran.com/archives/4018)是必要的。算法

若是说前一篇文章文章在 LsSize 提出以前的是基础,LsSize 是应用,那么对于这篇文章来讲,LsSize 是基础,而这里是其的综合应用,我之初衷是其扩展性和兼容性,激发读者思惟。也许你并无体会出 LsSize 的强大,而实际上,它能作的比你想象的要多的多,这是前话 ~spa

ShoAll 模式的兼容

首先 LsSize 能知足 ShowAll 模式的须要,由于开始就是把 LsSize 看成 ShowAll 中的 WinSize 来设计的。 而且能够为背景作装饰,而在游戏设计之时并无什么区别,LsSize 能够设定显示区域的大小,使背景层与 LsSize 分离(这一点在上一篇文章最后已经提到),从而保证了游戏的元素不会超出 LsSize 而露出到 VisibleSize 的区域内。设计

NoBorder 模式兼容

为何说 NoBorder 兼容模式,它自己不就是 NoBorder 么,它与实际的 NoBorder 区别又在何处,有何优点?首先说说兼容,使用此模式,并不影响 你继续使用 VisibleSize 和 VisibleOrigin(之后简写 Visible),你能够不使用 LsSize 的参考点,而使用 Visible 的相关值获取屏幕的拐点,游戏元素按照 Visible 来设置也可。下面详细介绍基于 LsSize 的 NoBorder 和原油 NoBorder 的区别以及其优点。code

咱们设想这样一个 实际状况 。咱们须要一套资源图片,作为在适合分辨率的资源展现,当屏幕的大小分辨率在 854×480,800×480,728×480 (横屏下:为何高度一样是 480 而宽度有这么多值 : P 这也是屏幕适配万恶之一了吧) 时,咱们使用一套资源,当高度小于 480 时,咱们使用另外一套小的资源是合理的设计。而这里咱们的资源宽姑且先不论,高必定是 480 最为合适了,最接近此分辨率的图片。那咱们使用 NoBorder 的时候该 设置 WinSize 为多少 了呢?htm

基于 854×480 设计!好,那么当程序跑在 854×480 的屏幕上,正好满屏显示,而图片资源并无放大或者缩小,或者说基于像素点点对点显示的。可是当这样设计的 WinSize 跑在 800×480 和 728×480 分辨率会如何?也许已经知道了,为了保证小于 854 那一小块区域的显示,画面将会缩小那么一点点,也许在现在屏幕的 ppi 日益渐高的状况下,并不十分明显,但画面必定是有那么一点模糊了。同理能够碰见,不论 WinSize 如何设置,在 三种少量不一样分辨率下,显示的效果确定略有不一样。而分辨率差异越大,这种效果就越明显。blog

注:细心的朋友已经读出上文描述中出现的 Bug ,并多谢指出问题的朋友。下面修复 Bug 并从新描述问题的状况 ~游戏

折衷方案,咱们基于 800×480 设计,那么此时出现的状况是,当跑在 800×480 的屏幕上时,正好满屏显示,而图片并无任何放大或者缩小,或者说基于像素点点对点显示的。而当这样设计的 WinSize 跑在 728×480 和 854×480 的分辨率会如何? 854×480 相比 800×480,前者的宽高比要大于后者,因此它是宽对齐的,这意味着,画面有所放大,而上下将会有一部分残缺,此时设计高度将会失去参考价值。728×480 相比 800×480 ,前者的宽高比小于后者,因此它是高对齐的,此时画面并无缩放,只是横向截取了小部分,这样的状况是因为 NoBorder 的实现机制所决定。固然咱们能够将设计的宽度设置的很宽很宽,以保证高对齐,哈~可是魔(设计宽度)高一尺,道(实际宽度)高一丈,倒不如使用后文提到的“固定高度”方式了~ 而这里的 854×480,800×480,728×480 等数据只是屏幕适配等问题的“缩影”图片

读到这里也许已经发现了,LsSize 已经完美(这里的完美,并不是只此特殊状况下的解决方法,而是总览全文,基于 LsSize 的设计理念,其兼容性和可扩展性,显然在此时,固定高度是更好的实现方式)的解决了这个问题,动态 WinSize ,一个合理的设计,我梦将 LsSize 设定为 720×480,而且使用 高度为 480 的图片资源,而宽度能够往大了设计,好比 854×480 的图片资源,读过前文 LsSize 的实现原理,咱们能够知道,在这三种状况下,屏幕的画面并无缩放,由于实际的宽度老是大于 720 ,从而达不到缩放的条件。480 高度的图片,可以正好填充 480 高度的屏幕,而图片的宽度往大了设计,在宽度稍微小的屏幕下,会被截取一部分,但就显示效果来讲,并无什么损失,而游戏的元素位置能够用原来的方法基于 Visible 来设计。资源

为何能够作到如此!本来的 NoBorder 经过固定 WinSize 根据屏幕宽高比缩放,因此会有不一样程度的缩放,而 LsSizeNoBorder 的设计实现,经过屏幕宽高比来得到 WinSize 的值,以保证 LsSize 总能在屏幕上正好所有显示。

LsSizeNoBorder 比 NoBorder 好,好多少,这就仁者见仁,智者见智了 ~

kResolutionFixedHeight,kResolutionFixedWidth 扩展兼容模式

FixedHeight 和 FixedWidth 是什么模式,若是你试用了最新版的 cocos2d-x (2.1.3)就能发现这两种模式,一种是固定设计时的高,一种是固定设计时的宽。而在当前的 2.0.4 并无这两种模式,而如今,你能够经过 LsSize 来实现这两种模式。存在既是合理,FixedHeight 和 FixedWidth 的存在是合理的,好比咱们写一个横版过关游戏,一样是三种分辨率 854×480,800×480,728×480 使用固定设计高度的方法,能够避免在 NoBorder 中会根据宽度而作的缩放。

而在 LsSizeNoBorder 中好似也实现了相同的功能!但注意有一点区别,在 LsSizeNoBorder 中,实际屏幕高度为 480 ,若是宽度小于 720 时,那么画面会缩放,而这里新模式固定高度不会。若是咱们想让 LsSize 实现这种功能怎么作,咱们将对 LsSize 的设计稍做扩展,上篇文章的代码:

CCSize frameSize =CCEGLView::sharedOpenGLView()->getFrameSize();
// 设置 LsSize 固定值
CCSize lsSize =CCSizeMake(480,320);
 
float scaleX =(float) frameSize.width / lsSize.width;
float scaleY =(float) frameSize.height / lsSize.height;
 
// 定义 scale 变量
float scale =0.0f;// MAX(scaleX, scaleY);
if(scaleX > scaleY){
// 若是是 X 方向偏大,那么 scaleX 须要除以一个放大系数,放大系数能够由枞方向获取,
// 由于此时 FrameSize 和 LsSize 的上下边是重叠的
scale = scaleX /(frameSize.height /(float) lsSize.height);
}else{
scale = scaleY /(frameSize.width /(float) lsSize.width);
}
 
CCLog("x: %f; y: %f; scale: %f", scaleX, scaleY, scale);
 
// 根据 LsSize 和屏幕宽高比动态设定 WinSize
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(lsSize.width * scale,
lsSize.height * scale, kResolutionNoBorder);

咱们的实际缩放系数,是根据 scaleX 和 scaleY 的大小来判断,依据哪一个方向缩放,从而在显示效果上是高对齐仍是宽对齐。而想要固定是高度对其仍是宽度对其,那只要换用以下方法便可:

// 要实现这种功能,咱们须要作的就是算得 缩放系数,缩放系数由 原来的设计稍做演变便可
// 因为 NoBorder 的缩放是根据 scaleX 和 scaleY 的熟大熟小来判断缩放系数是参照横向仍是竖向
// 固咱们须要两个先决条件,固定的方向 和 缩放的参照方向,而获得以下算法
 
// 固定高度
if(scaleX > scaleY)
scale = scaleX /(frameSize.height /(float) lsSize.height);
else
scale = scaleX /(frameSize.width /(float) lsSize.width);
 
// 固定宽度
if(scaleX > scaleY)
scale = scaleY /(frameSize.height /(float) lsSize.height);
else
scale = scaleY /(frameSize.width /(float) lsSize.width);
  1.  

下面经过几张效果图展现 固定高度 和 固定宽度 效果:

显示效果:(NoBorder 固定高度模式 ;FrameSize = 520×320; LsSize = 480×320; WinSize = 动态获取)

 图片

显示效果:(NoBorder 固定高度模式 ;FrameSize = 520×360; LsSize = 480×320; WinSize = 动态获取)

 图片

显示效果:(NoBorder 固定宽度模式 ;FrameSize = 480×360; LsSize = 480×320; WinSize = 动态获取)

 图片

显示效果:(NoBorder 固定宽度模式 ;FrameSize = 480×300; LsSize = 480×320; WinSize = 动态获取)

 图片

如图所示,咱们固定了一个方向,使得这个方向上的设计长度正好填充屏幕,而另外一个方向上会有所延伸或截取,而此时若是想或者屏幕拐点,能够配合 Visible 的显示区域算得。而这也正式 cocos2d-x 2.1.3 所实现的功能,而若是你此时为了稳定而使用 2.0.4 stable 版本,那么就能够经过这种基于 LsSize 的设计方法实现 FixedHeight 与 FixedWidth。 而在未来后续版本稳定,也能够很平滑的升级到使用自带的方式替换,其显示效果同样,只是后续版本 cocos2d-x 在内部将它封装了而已。

kResolutionLeafsoar 模式的核心思想

透过现象看本质!基于固定 LsSize 的动态 WinSize 设计。之因此可以兼容这么多模式而且有所增强,在于 LsSize 在 FrameSize、WinSize、VisibleSize、VisibleOrigin等概念以外的存在,而且经过动态计算 scale 而游走于此等之间。它的存在并不依赖于 这些已有概念,而反过来,让已有的概念去依赖 LsSize 。从而保持设计上的灵活性与扩展性。

相关文章
相关标签/搜索