[原创]cocos2d-x研习录-第三阶 多分辨率适配器
在移动终端(智能手机)平台下开发游戏一般都会涉及到屏幕多分辨率适配问题,原因是手机款式多种多样,不同的款式存在有不同的尺寸,即使尺寸相同又可能存在不同的分辨率。
手机屏幕尺寸:指手机屏幕对角线长度。
手机分辨率:指屏幕上横、纵的总象素点数。分辨率越高,即总象素点数越多,屏幕显示效果越好。
上面我们介绍了手机尺寸和分辨率的概念,结论是手机屏幕显示效果是由尺寸和分辨率决定的。相同尺寸不同分辨率手机,分辨率越高显示效果越好;相同分辨率不同尺寸的手机,尺寸越大显示效果越差。
有了这两个概念,我们要开始探讨多分辨率适配问题。
什么是多分辨率适配问题呢?举例说明一下。
(1)有两款手机,屏幕尺寸相同,但分辨率不同;手机A分辨率为320*480,手机B分辨率为640*960。现在我要将一张分辨率为320*480的图片显示到两部手机屏幕上,结果将会如何呢?
答案:手机A会全屏显示图片,手机B只有四分之一屏幕会显示图片。
(2)有两款手机,屏幕分辨率都为320*480,但尺寸不同;手机A尺寸是5寸屏,手机B尺寸是3寸屏。现在我要将一张分辨率为320*480的图片显示到两部手机屏幕上,结果将会如何呢?
答案:手机A和手机B都全屏显示图片。
由上两个例子可以知道,多分辨率适配问题只与手机屏幕分辨率有关,与屏幕尺寸无关。如果所有手机都采用相同分辨率,那么将不存在多分辨率适配问题。但事实上,这肯定是不可能的。
所以,我们在开发过程中形容手机屏幕大小,可以忽略屏幕的尺寸,只使用分辨率。
那么我们解决多分辨率适配问题的目的是什么呢?根本目的当然是实现不同分辨率设备上用户体验的统一。换句话说,就是不同分辨率设备显示效果虽然可以不同,但显示的内容和样式是相同的。
我们先思考一下应该如何解决举例(1)中多分辨率适配问题导致的两款手机上同一图片显示的不一致。
很容易想到有三种思路:
思路1:使用不同的资源适配不同分辨率的设备。针对举例(1)就是再做一张640*960的图片,通过获取设备的分辨率使用相应分辨率的资源。这种方案仅适用于设备分辨率比较少的情况。如果设备分辨率很多,那么势必要针对每一种设备分辨率做一套资源,那将是游戏美工的噩梦。同时,发行时游戏资源包将变得异常大,如果采用分设备发行游戏资源包,维护和管理将变得极为困难。
思路2:使用同一资源通过资源缩放适配不同分辨率的设备。针对举例(1)就是在640*960屏幕分辨率下,将320*480的图片放大一倍后再显示。这种方案可能存在的两个问题:一是资源的分辨率比设备分辨率大,资源存在浪费;二是资源的分辨率比设备分辨率小,势必放大资源,影响显示效果。
思路3:结合方案1和方案2,使其在显示效果和资源使用率上达到平衡。
Cocos2D-x在cocos2d-2.0-x-2.0.4版本提供了多分辨率适配问题的解决方案,在这之前开发者只能自己想办法解决,而该解决方案其实就是以思路2作为依据的。
下面我们就来学习一下,Cocos2D-x是如何解决多分辨率适配问题。Cocos2D-x引入了几个全新的概念,需要理解这些概念的含义才能明白Cocos2D-x的解决方案。
·设计屏幕大小(designSize/winSize):也可以理解为逻辑屏幕大小。它是Cocos2D-x框架为开发者提供的标准界面,开发者只需要基于设定的设计屏幕大小进行开发,至于标准界面与不同设备之间的适配,则由Cocos2D-x框架实现。通过标准界面就达到了隐藏不同设备的差异,使游戏开发所有资源的映射都基于标准界面。
·实际屏幕大小(screenSize):它表示物理屏幕大小。实际上就是指不同设备的分辨率大小。Cocos2D-x框架需要获取该值,实现从设计屏幕大小到实际屏幕大小的适配。
·可视屏幕大小(visibleSize):它是建立在设计屏幕大小概念基础上的,表示能够显示的区域大小。它是设计屏幕大小的子集。
有了这些概念,就可以进一步理解Cocos2D-x的解决方案的原理。它通过获取实际屏幕大小和开发者设置的设计屏幕大小,就可以求出它们之间的比例;在渲染的时候,把资源按照这个比例来缩放绘制。
在求实际屏幕大小与设计屏幕大小的比例时,可能出现宽高比不同的情况。例如设计屏幕大小为480*320(宽高比=480/320=1.5),而实际屏幕大小为1024*788(宽高比=1024/768=1.3)。这时宽高比不同,资源也就无法缩放来填满屏幕。
Cocos2D-x定义了三种模式来处理宽高比不同的情况,在实际开发中开发者可以根据需要选择不同的模式:
·kResolutionExactFit模式:完成适应模式。通过拉伸资源的方式填满屏幕;也就是以宽比和高比作为缩放比例分别进行缩放,但这会使资源产生变形。如下图((红色线框指屏幕):
·kResolutionNoBorder模式:无边界模式。通过宽高等比缩放,但缩放比例取宽比和高比中最大的那个。这可以确保资源不变形缩放,但这会使有一部分资源超出屏幕。如下图(红色线框指屏幕):
·kResolutionShowAll模式: 全显示模式。通过宽高等比缩放,但缩放比例取宽比和高比中最小的那个。可以确保资源不变形缩放,但这会使资源无法填满屏幕。如下图(红色线框指屏幕):
不使用多分辨率适配,图片显示时将不会被压缩,由于图片的分辨率为960*640,而实际屏幕大小 为480*320,所以屏幕只能显示图片的一半。
我们再来看一看宽高比不同的情况下,多分辨率适配的三种模式的区别,如下:
条件设置1:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionExactFit);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionExactFit模式后,图片被拉伸显示。
条件设置2:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionNoBorder);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionNoBorder模式后,图片未变形,但图片超出了屏幕显示。
条件设置3:
eglView->setFrameSize(480,150);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(960,640, kResolutionShowAll);
运行程序,结果如图:
可以看出在宽高比不同的情况下,使用kResolutionShowAll模式后,图片未变形,但图片未能填满屏幕,两边有黑色空隙。
现在应该理解Cocos2D-x的多分辨率适配的三种模式吧。现在我们再来看HelloCpp中的下面一段代码:
bool HelloWorld::init()
{
...
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();//可视屏幕大小
CCSize winSize = CCDirector::sharedDirector()->getWinSize();//设计屏幕大小
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); //可视屏幕原点...
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));//设置精灵位置为屏幕中心...
}
在条件设置1(kResolutionExactFit模式)中,运行结果如下:
visibleSize->(960,640)
winSize->(960,640)
origin->(0,0)
在条件设置2(kResolutionNoBorder模式)中,运行结果如下:
visibleSize->(960,300)
winSize->(960,640)
origin->(0,170)
在条件设置3(kResolutionShowAll模式)中,运行结果如下:
visibleSize->(960,640)
winSize->(960,640)
origin->(0,0)
可以看出,在kResolutionNoBorder模式下,当宽高比不同时,可视屏幕大小将小于设计屏幕大小。定义可视屏幕大小的目的就是因为在kResolutionNoBorder模式下,渲染绘制资源可能会超出屏幕显示。在设置精灵对象位置时使用可视屏幕大小而不是设计屏幕大小,可以确保在任何模式下都能够正确显示。
Cocos2D-x的多分辨率适配解决方案就讲到这里。我们可以认识到,其实Cocos2D-x提供的三种可选模式都存在着不同的缺陷,我在博客上曾经看到一篇文章,作者试图基于kResolutionNoBorder模式和kResolutionShowAll模式的特点提出新的适配解决方案。至于这个新解决方案已经超出了本内容的范围,有兴趣的同学可以自己去琢磨和研究。
----------------------------------------------------------------------------------------------------------------------------------------
注:本人在本博客的原创文章采用创作共用版权协议(http://creativecommons.org/licenses/by-nc-sa/2.5/cn/), 要求署名、非商业用途和保持一致。要求署名包含注明我的网名及文章来源(我的博客地址:http://www.cnblogs.com/binbingg)。
[原创]cocos2d-x研习录-第三阶 多分辨率适配器的更多相关文章
- [原创]cocos2d-x研习录-第三阶 特性之物理引擎
游戏物理引擎是指在游戏中涉及物理现象的逻辑处理,它用于模拟现实世界的各种物理规律(如赛车碰撞.子弹飞行.物体掉落等),让玩家能够在游戏中有真实的体验. Cocos2D-x中支持Box2D和Chipmu ...
- [原创]cocos2d-x研习录-第三阶 特性之粒子系统
我想接触过游戏引擎的同学,对粒子系统应该不会陌生.它用于解决由大量按一定规则运动(变化)的微小物质在计算机上的生成和显示问题.粒子系统在游戏中有着非常广泛的应用,可以模拟很多现象,如火花.爆炸.烟雾. ...
- [原创]cocos2d-x研习录-第三阶 背景音乐和音效
在游戏中,音效是一个不可或缺的部分,它可以为我们的游戏增加效果.音效在游戏中一般分为长时间的背景音乐和短促的特效音乐.Cocos2D-x支持多种常见音乐格式(mp3.wav等). Cocos2D-x提 ...
- [原创]cocos2d-x研习录-第三阶 特性之瓦片地图集
由于一张大的世界地图或背景图片往往可以由屈指可数的几种地形来表示,每种地形对应于一张小的图片,我们称这些小的地形图片为瓦片.把这些瓦片拼接在一起,组合成一个完整的地图,这就是瓦片地图集的基本原理. C ...
- [原创]cocos2d-x研习录-第三阶 特性之调度器
在游戏中,经常会周期执行一些检测.操作或更新一些数据等,我们称之为调度.Cocos2D-x中将调度封装为类CCScheduler,方便在游戏开发中使用.我们一起来学习一下,CCScheduler具有哪 ...
- [原创]cocos2d-x研习录-第三阶 特性之动作
在前面的Cocos2D-x的概念类中,我们了解到节点类CCNode.导演类CCDirector.场景类CCScene.布景层类CCLayer和精灵类CCSprite等,这些类都是构成游戏画面的基本元素 ...
- [原创]cocos2d-x研习录-第三阶 特性之按键与虚拟键盘
Cocos2D-x引擎支持按键事件,它能检测设备的键盘输入并处理相应的事件.而基于不同操作系统的移动设备,可供用户操作的按键数量和功能都存在差异. Cocos2D-x使用CCKeypadDeleg ...
- [原创]cocos2d-x研习录-第三阶 特性之加速度传感器
智能手机的游戏与应用中,也经常会用到加速传感器事件来丰富用户的体验,比如飞翔的企鹅(英文AirPenguin)游戏就是通过加速度传感器来控制角色的移动和跳跃方向.下面学习Cocos2D-x中如何使用加 ...
- [原创]cocos2d-x研习录-第三阶 特性之触屏
游戏跟视频最大的区别就是互动,而手游(基于智能手机)主要靠触摸屏幕.重力传感和虚拟键盘等方式实现互动.这里主要记录Cocos2D-x对玩家触屏操作的处理. 在Cocos2D-x中触屏分为单点触屏和多点 ...
随机推荐
- 2014年7月份第3周51Aspx源码发布详情
Froor高校校园网站源码 2014-7-18 [VS2010]源码介绍:这是一款有关高校门户网站的毕业设计源码,功能相对比较完善,界面也比较美观,对门户网站感兴趣的朋友们可以下载研究一下.该源码功 ...
- LeetCode Reorder List
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {} }; class Solution ...
- DOM扩展之 专有扩展
11.4.3 contains() 方法 用来确定某个节点是不是另一个节点的后代. 注:a.contains(a) 也是返回true.说明contains方法搜索是从自身开始的. DOM Level ...
- 排序系列 之 简单选择排序及其改进算法 —— Java实现
简单选择排序算法: 基本思想: 在待排序数据中,选出最小的一个数与第一个位置的数交换:然后在剩下的数中选出最小的数与第二个数交换:依次类推,直至循环到只剩下两个数进行比较为止. 实例: 0.初始状态 ...
- C语言文法分析
程序 → <外部声明>|<程序><外部声明> <外部声明> → <函数定义> | <声明> <函数定义> → < ...
- 关于spring中无法将service注入到servlet中的问题
首先,servlet是动态网页项目区别于普通的java项目的,是动态网页项目中web.xml主要配置文件管理的,而spring只能管理普通的pojo,而没办法直接注入,尽管你的注入方式和配置方式都没有 ...
- Jsonp理论实例代码详解
什么是Json?JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - ...
- Hello World!
博客园的效率真是高啊,开通博客的申请刚刚递交几分钟就通过了,赞一下博客园的程序员们,这么晚还在工作! 博客主要用来记录自己学习HTML5.CSS.PHP等web前端技术的经历,因为是初学者,所以发的文 ...
- Tomcat8 localhost+端口可以访问Manager APP,而IP+端口不可以访问 解决办法
localhost + 端口可以正常访问Manager APP,而IP + 端口不能访问Manager APP,报403错误.(我的主机环境是Ubuntu16.04) 前提是你已经配好了tomcat_ ...
- Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path 解决办法
返回数据解析错误 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT ...