Cocos2d-x适配解决方案及原理分析

前言废话:

Cocos2d-x是一套跨平台开发的2D游戏引擎,我本人主要使用它开发IOS和Android两个平台。大部分手游都面临一个很重要的问题就是屏幕适配,Android碎片化问题尤为严重,屏幕分辨率多种多样。经常看到会有人在论坛问起适配相关的问题。2014年我本人打算开始写点博客来记录并分享一些技术方面的东西,眼下就从cocos2d-x开发的适配方案开始写吧。

本文程序开发环境:win7 + vs2012+cocos2d-x2.1.5

在cocos2dx 2.0以后的版本有提供官方的适配方案,我先从无适配模式开始讲,然后再解释官方的5种适配方案,最后给出2种自定义的适配的方案。

先看一段代码热身:

以下是生成的cocos2d-x工程中win32平台下main.cpp中main函数的代码,主要是红色的那句代码,通过修改传入不同的参数来模拟不同屏幕分辨率的手机。这也是在windows平台上调试适配方案最棒的一个优点~。

    AppDelegate app;
    CCEGLView* eglView = CCEGLView::sharedOpenGLView();
    eglView->setViewName("cocosTest");
    eglView->setFrameSize(800,480);//这句设置窗口大小
    return CCApplication::sharedApplication()->run();

1.无适配模式

我们先来看下面两张图:



两张图都是在无适配模式下的运行结果,第一张图运行的窗口大小为480x320(模拟手机分辨率为480x320的设备),第二张图的窗口大小为800x480.
窗口中的图片就是默认生成的工程中自带的图片,大小为480x320。可以看到如果手机分辨率和图片大小是一样的,图片自然铺满整个屏幕, 如果屏幕分辨率变了呢?图中显示的结果也是我们能够理解的,窗口大小是800个像素宽,480个像素高,图片才480像素宽,320像素高,居中放置,自然是不能铺满屏幕的。而这也是我们适配模式需要解决的问题!(Android设备分辨率几十上百种,我相信没有美工妹纸愿意为了一个游戏出几十上百套不同尺寸的图,咳……即使妹纸愿意,App Size都不会同意的~各个游戏发布平台都是对程序安装包的大小有限定的。)

2.五种官方适配模式

在讲官方的五种适配模式之前,我们得先了解一些概念。 frameSize winSize  visibleSize visibleOrigin。
其中frameSize是最好理解的,它指的就是设备的分辨率尺寸。上图中图一的frameSize就是480x320,图二的frameSize就是800x480;
后三个概念,实际都是围绕概念winSize而产生的,而我个人认为,winSize概念也是解决适配问题的最核心的东西。那到底是什么是winSize呢?让我们暂时回到无适配模式下看程序出现了什么状况:实际屏幕分辨率各种各样,图只有一套,一套图并不能占满各种分辨率的屏幕。我们确实只有一套图,换我们自己来设计适配方案,应该怎么来解决这种问题呢?答案是:缩放!这个答案很显而易见。当在大分辨率的屏幕上时,我们缩放这张图让图片依然占满屏幕。而实际上cocos2d-x也是通过缩放来适应各种屏幕的。但如果适配模式就是单纯缩放的话,那也就没什么好讲的了。重点就在于缩放比例的控制。
下面这句话尤为重要,需要牢记:
cocos2d-x帮我们缩放了整个游戏布局,对于适配模式,我们只需要关心缩放的比例!而适配模式的核心也在于缩放比例的计算!
看了上面这句话,一个问题也被带出来了,假如我缩放比已经得到了,那我该从哪个尺寸开始缩放呢?!ok。答案其实上面已经提到了,这就是winSize!winSize这个尺寸就是我们设计游戏的一个基础尺寸。我们设定好winSize,引擎根据当前设备不同的分辨率会计算一个缩放比,然后用这个尺寸乘上计算出来的缩放比,就会得到真实的游戏界面的窗口大小。而visibleSize就是我们在设备上能看到的游戏界面的一个尺寸,visibleOrigin就是这个可见尺寸界面的左下角。到此,winSize和visibSize的理论概念已经解释了。但是!我相信没有我接下来这么几句话的解释,如果之前没做过适配,大部分人肯定会对visibleSize有错误的认识。
visibleSize和winSize是同一级的东西!它们是因为适配而设计出来的概念,与屏幕的真实像素分辨率尺寸无关!
比如现在我们使用了某个适配模式,设置的winSize为480x320.现在我们把程序拿到分辨率为960x640的设备上去运行。这个时候,引擎把我们的游戏界面缩放两倍展示出来,刚好占满屏幕,winSize是480x320,是我们自己设计的,大家都能理解。引擎就是在这个基础上进行缩放的。那此时的visibleSize是多少呢?根据上面的解释:visibleSize就是我们在设备上能看到的游戏界面的一个尺寸。我们能看到整个屏幕,屏幕的分辨率为960x640。可visibleSize并不是960x640而是480x320!请牢记,visibleSize是你能看到的整个游戏界面,这个游戏界面是指我们设计的winSize。visibleSize和winSize是同一级的,我们能看到整个winSize,那visibleSize的大小就是和winSize一样大的。
说了那么多,是时候看具体的代码和显示效果了。
下面代码是设置适配模式的关键几句,我先从最简单的ExactFit适配模式说起。
    CCDirector* pDirector = CCDirector::sharedDirector();
    CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
    pDirector->setOpenGLView(pEGLView);
    pEGLView->setDesignResolutionSize(480,320,kResolutionExactFit);//主要是这句设置适配模式
先简单解释下setDesignResolutionSize这个函数。这是设置适配模式的函数,前两个参数传的就是winSize的尺寸,第三个参数传的是适配模式类型(适配模式类型是引擎定义的一个枚举类型)。至于为什么前两个参数就是winSize我在介绍完几种官方适配模式的使用后,分析引擎源码的时候再详细解释。
ExactFit适配模式简单粗暴,它直接把我们给定的winSize拉伸到和屏幕真实尺寸一样大,在缩放过程中长和宽的缩放比是不一定相等的。例如下面两图:

左边图片是在960x640窗口下运行。很明显相对于480x320的winSize来说,长宽的缩放比都是2倍,这是一个等比的缩放!图片并未变形。右边图片是在800x480窗口下运行。这个窗口相对于winSize的缩放比:长->800/480 = 1.66666......宽->480/320 = 1.5.这不是一个等比的缩放。长的方向要缩放得多一些,很明显图片确实被压扁了。如果窗口再长点,图片形变将更明显。在真实的设备中,分辨率很明显不会都刚好相对于我们设计的winSize等比缩放。所以采用这种模式图片大部分会被拉伸变形。这个致命缺点就是绝大大部分项目不敢选择这个适配模式的原因。
看来这么简单粗暴的直接缩放并不是很好,我们再来看接下来的两种官方适配模式ShowAll和NoBorder。设置也很简单,就是设置适配模式的那个函数的第三个参数改下即可:
	pEGLView->setDesignResolutionSize(480,320,kResolutionShowAll);//ShowAll适配模式
	pEGLView->setDesignResolutionSize(480,320,kResolutionNoBorder);//NoBorder适配模式
为什么把这两个模式放一起来说呢,因为这两种模式实际上是刚好相对的两种,在了解了ExactFit适配模式后再来看这两种都很好容易理解。ExactFit模式的弊端在于没有等比缩放。长和宽的缩放比都不相等,确实让人家很难选择啊 快哭了!到底该怎么缩放啊?而ShowAll和NoBorder两种模式就很坚决,他们要做的就是保证是等比缩放!为什么说这两个模式是相对的呢?就是因为在出现上面那种情况的时候(winSize为480x320,实际分辨率为800x480),他们各自都是按一个缩放比来缩放游戏界面。ShowAll模式下,引擎是按照较小的那个缩放比来缩放游戏界面,也就是按1.5倍缩放,而NoBorder模式恰好相反,它会按照较大的缩放比来缩放,也就是按1.6666倍来缩放。既然都是按等比缩放,那图片肯定是不会变形的了。可屏幕的利用率就有问题了啊,请看下面两幅图:

左边的图片是在showAll模式下运行的。游戏界面是按较小的缩放比(1.5倍)来缩放的,不等比缩放的时候长应该缩放1.6666倍的,现在由于等比缩放,只放大了1.5倍,很显然长的实际宽度算出来应该是480 * 1.5 = 720个像素!所以显示出来的有游戏面两边是有黑边的(宽的缩放比大于长的缩放比的时候,是上下有黑边)。而且这个黑边还是无法通过图片遮住的,至于为什么,在之后源码解析的时候再做解释。
右边图片是在NoBorder模式下运行的,游戏界面按较大的缩放比(1.6666倍)来缩放的。同理:不等比缩放的时候宽只应该缩放1.5倍的,现在由于等比缩放,却放大了1.66666倍,所以宽计算出来的宽度为:320 * 1.666666 = 533个像素。所以整个游戏界面是超出了设备屏幕的真实大小。由于程序所用的图四周为纯色,所以看起来不明显。但是我们注意看helloworld这个label。我在设置其位置的时候是做了一定计算的,保证他能在屏幕内显示,在图中该label的位置明显已经和cocos2dx的logo重合了。所以背景图的显示大小实际上是比屏幕尺寸大的,上下两边有凸出去一部分。
相信ShowAll和NoBorder两种模式也是很好理解的。他们均保证了等比缩放。图片不被拉伸变形。在设定好了winSize的情况下,在真实设备运行中,他们分别选了其中一个缩放比来进行等比缩放。它们的优缺点也很明显。ShowAll:能保证所有的图片都显示在屏幕内,但是屏幕有可能不能充分利用,留下黑边。NoBorder:保证屏幕充分利用,但是游戏内容会超出屏幕,我们需要动态的计算精灵的坐标才能保证所有精灵显示在屏幕可视范围内。对于现在的游戏来说,基本上都是没法接受黑边的情况了,所以相比看来,NoBorder模式还算是个不错的模式。实际上最后提出的其中一个自定义适配模式就是在NoBorder的基础上修改的。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值