cocos2d-x作为著名的cocos2d游戏开发框架的C++实现者,最近一年发展迅猛。越来越多的app使用它实现快速多平台部署,从最初的ios,android,win32等到新近的html5,实现移动,客户端到浏览器全覆盖,不得了~~

开发移动应用的屏幕适配和爱情一样是一个从洪荒时代就存在的永恒命题,根本目的是实现在不同设备上用户体验的统一。
cocos2d-x在cocos2d-2.0-x-2.0.4版本之前没有提供解决的方案,开发者只能自己解决,其中一些方法见 这里

从2.0-x-2.0.4开始,勤劳的cocos2d-x团队终于着手解决这个问题了~赞! 下面用一个实例分析一下其实现原理,官方说明文档见 这里

==============================  大家好,我是正文开始之前华丽的分隔线   ===========================

新建一个带helloworld例子的工程,跑起来是这样的:

窗口尺寸为480x320,背景火蓝精灵的图片原始大小就是480x320,正好铺满屏幕。

我们就从这里开始变化。。。
首先,模拟分辨率为960x640的屏幕,看看程序会是什么样子。
会修改win32下窗口尺寸么?如果你是从2.0-x-2.0.4之前的版本直接跳过来的,比如我(源自1.0.1-x-0.11.0。。。“源自xxxx”形容酒很有档次,对于编程么。。还是要与时俱进,改进工作作风密切联系群众~),第一反应就是到AppDelegate.cpp里去找设置win32窗口大小的代码。
很遗憾,你找不到熟悉的"CC_TARGET_PLATFORM == CC_PLATFORM_WIN32",新版本把设置win32窗口尺寸移到了main.cpp里面,
如下图:

从代码结构来讲,这样更合理,因为AppDelegate.cpp是与平台无关的程序逻辑入口,里面不应该还包含大量不同平台的适配代码。
交给win32自己的main.app去设置,让上帝的归于上帝,凯撒的归于凯撒!

接上述,把eglView->setFrameSize(480,320);  改为eglView->setFrameSize(960, 640);  模拟分辨率为960x640的屏幕,运行效果:

ok,背景图尺寸是480x320,在960x640屏幕下自然就填不满,很合理~

好,需求来了:我们想要的结果是不论在什么分辨率下,用户都应该看到背景图填满了屏幕!

so,解决方案:
1,使用不同的资源适配不同的屏幕,可以通过判断屏幕的分辨率来设置加载不同目录的资源。
2,使用一套资源,在不同的分辨率下匹配屏幕进行缩放。

一个个来,先说方案一,既然要为不同分辨率使用不同资源,那就再做一张图案一样的火蓝精灵背景图,尺寸为960x640,
用于分辨率为960x640的屏幕。在工程Resources目录下新建两个目录:

"iphone"目录存放480x320的背景图和按钮图标,"iphone-retina"存放960x640的背景图和按钮图标。
这两个目录名字随意,再看到AppDelegate.cpp,修改代码如下:

再运行程序:

肿么样,框架就按照设置找到了960x640的背景图,屏幕又恢复了不空虚不寂寞的状态 
这里要注意:想获取设备屏幕实际分辨率需要使用CCSize szFrame = pEGLView->getFrameSize();
而不是之前版本的CCDirector::sharedDirector()->getWinSizeInPixels(); 这个函数另有含义,后文会介绍。

but,面对全世界那么多的移动设备,那么多的分辨率,你hold住么?就算你hold住,你的美术妹纸们hold住么?
一种分辨率就出一套匹配的美术资源。。“希望你能陪我到地牢到天晃,希望你能陪我到海叫到天哑”。
就算真有以做地老天荒牌游戏为荣的团队,出来的安装包之大,也会让用户下载到地老到天荒~
so,这不是个好办法。

那看看第二种方案,对资源进行缩放,还原Resources目录的结构:

现在还是只有一张480x320的背景图,怎么改呢?AppDelegate.cpp里修改:

再次运行,amazing!屏幕再次不空虚不寂寞~

分析:
designResolutionSize是一个新的概念,它让一切与坐标,尺寸相关的数据彻底摆脱了屏幕分辨率的羁绊,或者说
由框架层来帮开发者完成转换,开发者需要的只是设置designResolutionSize。告诉框架你在什么样尺寸的场景下
做的资源,比如此例,背景图原始尺寸480x320,需求是刚好填满屏幕,那么就应该告诉框架“嗨,我设计时是以
480x320的屏幕为标准的,你帮我转转”,框架就会回答你“放心吧!” 那么框架究竟如何实现的呢? 跟踪
pEGLView->setDesignResolutionSize(480, 320, kResolutionNoBorder);

可以发现,框架是获取了实际分辨率和开发者designResolutionSize的比例,渲染的时候把图片按照这个比例来缩放绘制。
拿本例来说,屏幕960x640,designResolutionSize为480x320,缩放比例为2,那么原始大小480x320的背景图,在绘制
时就会x2来绘制,也就是实际绘制成了960x640的大小,这样就填满窗口了!
请注意这里对不同ResolutionPolicy的处理,原理后文会分析。

ok,现在面对480x320和960x640的屏幕,你已经能写出自动适配的代码了(其实只有一句,框架的好处啊~~)
又来了新的需求,“那谁谁,你改一下代码,程序要能适应ipad2 ”,WTF!好吧,问候归问候,问题总要解决。
于是你开始想“ ipad2分辨率1024x768,就按刚才帅帅凡教我的到main.cpp里修改”,好,修改为1024x768,看效果:

ms填满了,你很满意,但是不对,右下角的按钮肿么快到屏幕外面去了?!仔细一看,不是填满是填太满,背景图都超出屏幕了。
这是肿么回事呢? 根源在于pEGLView->setDesignResolutionSize(480, 320, kResolutionNoBorder);第三个参数,找到定义:

讲得很清楚了:
kResolutionExactFit:会靠拉伸来填满屏幕,本例来说背景图会变形来填充屏幕,因为1024:768=1.3, 480:320=1.5,宽高比不同,图片也就无法等比缩放来填满屏幕,只能变形了。
kResolutionNoBorder: 看不到黑边,实际就是宽高等比缩放,但缩放比例取宽比和高比之中大的那一个。
kResolutionShowAll:全部显示,可以理解为保证内容都显示在屏幕之内,实际也是宽高等比缩放,但缩放比例取宽比和高比之中小的那一个。

一般来说,我们希望设计时一屏的内容,用户在实际设备上也能在一屏内看到,拿本例来说,1024x768分辨率时,右下角的按钮却跑到屏幕外去了。看完上面的分析,你应该知道如何解决了: 对了,改变pEGLView->setDesignResolutionSize(480, 320, kResolutionNoBorder);第三个参数为kResolutionShowAll。 ok,看看效果:

bingo!背景图填满了屏幕(水平方向),按钮紧贴到右下角,可以满足基本的风格统一要求。
不过纵向上出现黑边,这个是实际分辨率的宽高比和设计分辨率宽高比不同造成的,无法通过框架层来解决。
只能交给开发者自己了,比如在代码里根据分辨率计算会出现黑边时,在黑边填充相应的图片等。一些解决方法见 这里

setPosition()的变化
之前版本可能已经习惯了CCNode::setPosition(const CCPoint &position);和CCNode::setPositionInPixel(const CCPoint &position);
但在新的版本里,只有setPosition(const CCPoint &position); 
这里传入的参数不是像素,也和传统的point有不同,它指的是在designResolutionSize参照下的坐标。
验证交给你自己来:比如设计分辨率为480x320,设置一个sprite的位置为240,160,在480x320分辨率下会发现它在屏幕正中,
模拟其他分辨率,960x640,1024x768,会发现它依然在屏幕中心,这就可了解240,160这个值跟实际屏幕分辨率已经无关了,
只和designResolutionSize有关,理解这一点至关重要,是后续开发正确空间感的基础!

CC_CONTENT_SCALE_FACTOR()的变化
首先enableRetinaDisplay()在新版本里取消了,将不会有什么retina设备上scalefactor为2的说法了,
因为designResolutionSize已经解决了按不同屏幕缩放的问题,所以CC_CONTENT_SCALE_FACTOR();始终返回1。
 
 
所以新版本里的定义已经过时了,无须理会。

当然,开发者可以通过CCDirector::sharedDirector()->setContentScaleFactor()来设置contentScaleFactor,这个系数可以理解为
图片原始尺寸和designResolutionSize的比值,这个比值将用来绘制图片。
如果只是一套资源按照不同屏幕分辨率缩放,可以不用理会。

getWinSize()的变化

CCDirector::sharedDirector()->getWinSize();   获取的是designResolutionSize
CCDirector::sharedDirector()->getWinSizeInPixels();  获取的是getWinSize*contentScaleFactor之后的值,和老版本一样。
如果contentScaleFactor为1,则这两个函数返回的值一样。 

使用kResolutionNoBorder策略时要注意的
CCSize szVisible = CCDirector::sharedDirector()->getVisibleSize();
CCPoint posVisible = CCDirector::sharedDirector()->getVisibleOrigin();
使用该策略时,因为标准背景图可能会超出屏幕,所以设置位置时需要已一个可视矩形为基准。
可以这样理解,szVisible就是你在实际设备上能看到的有效区域的宽高,posVisible就是这个有效区域的起始坐标,和szVisible构成一个可视矩形,一般来说这个可视矩形是设计分辨率下可视矩形的子集。

总结一下,cocos2d-x新的版本(对于从1.0.1-x-0.11.0上来的人)的确添加了不少新的功能,代码结构也更加合理,这些都是开发者之福,希望2dxteam继续加油!

文章转自  一嗑立扑死 :cocos2d-x屏幕适配原理分析

cocos2d-x 屏幕适配原理分析相关推荐

  1. Android dp方式的屏幕适配-原理(后期补充完整讲解)

    Android dp方式的屏幕适配-原理 传统所说的屏幕适配,其实是针对不同屏幕的UI尺寸适配,即在编写页面时使用了具体的dp.sp值后导致的其他问题. 我之前写过一些相关的文章和工具插件,也收到了很 ...

  2. android开发根据分辨率设置高度,最详细的Android屏幕适配方案分析

    为什么要屏幕适配 Android开发过程中我们常用的尺寸单位有px.dp,还有一种sp一般是用于字体的大小.但是因为px是像素单位,比方我们通常说的手机分辨例如1920*1080都是px的单位.现在A ...

  3. 移动端屏幕适配原理以及方法讲解

    序言: 今天周日,我正坐在黄埔区图书馆,思索着关于移动端屏幕适配的问题.作为一名年纪轻轻的前端马蓉,不,是码农,移动端屏幕适配的方案的帖子没读过100篇吧,也读过几十篇了.可是今天我又在思考这个问题了 ...

  4. Android用命名含sw的文件夹做屏幕适配原理

    基本概念 说到用命名含sw的文件夹做屏幕适配之前先说以下几个基本概念: 屏幕尺寸 屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米 比如常见的屏幕尺寸有2.4.2.8.3.5.3.7.4 ...

  5. 手机屏幕适配原理及实现

    为什么80%的码农都做不了架构师?>>>    手机屏幕是用户与 App 最直接的交互点  不同的分辨率下用户对我们的 App 具有明显的感观差异,主流分辨率的更新迭代却又完全独立于 ...

  6. cocos2d-x屏幕适配原理

    原文地址:http://m.blog.csdn.net/article/details?id=50827766 一.适配简介 如今市面上的手机种类越来越多,分辨率是千变万化的.但是我们做游戏开发,喜欢 ...

  7. Android开发之路:搞懂这几个问题,就掌握了屏幕适配原理

    前言概要: 1,进大公司还是小公司,真的有的选? 2,校招的潜规则 3,校招想进大厂怎么办 4,社招的潜规则 5,社招想进大厂怎么办? 前言 现在Android界的网络请求已经是OkHttp和Retr ...

  8. Android深色模式适配原理分析,android应用开发

    return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { Configuration.UI ...

  9. Android学习屏幕适配技能包

    屏幕适配 序言 相关重要概念 硬件 屏幕尺寸 像素密度ppi 分辨率 软件 密度 像素密度dpi 密度限定符 密度无关像素 比例无关像素 屏幕适配的原因 解决方案 今日头条适配方案 宽高限定符适配方案 ...

最新文章

  1. 在CentOS 6.3 64bit上安装ATS 5.3 LTS版本并测试
  2. 更新ADT到Android L的方法
  3. lisp填写明细表对话框_用AutoLisp定制acad的对话框
  4. [html] html6即将到来,你最期待的是什么特性呢?
  5. C语言常见基础错误大全总结
  6. PGM:贝叶斯网的参数估计2
  7. pb 执行insert 后return是否会自动提交_一条MySQL更新语句是怎么执行的?
  8. Altium Designer 学习笔记
  9. 什么是空号检测api接口?哪些行业会用到?
  10. react-router-dom v6 使用
  11. 杂谈——每日热量消耗
  12. 关系数据库:理解一二三范式
  13. html的div双线边框,设置div边框
  14. 小米路由器忘记管理密码后重置密码
  15. java visibility_[Java教程]display 与 visibility
  16. 捷达vs7测试_捷达vs7碰撞测试成绩
  17. 停车辅助系统的技术和变化
  18. Unity跑酷游戏中的路点生成算法
  19. AutoJS4.1.0实战教程---京东领京豆
  20. 宏任务与微任务面试题

热门文章

  1. 阿里云GPU服务器NVIDIA驱动安装与更新
  2. Spring框架,IOC,DI,AOP,单例多例,懒加载
  3. visual paradigm 时序图实用技巧
  4. 疫情都那么“狠”了,中国新能源汽车出口同比还能增长130%?
  5. 【LeetCode08】字符串转换整数
  6. 解决SQL Server 无法连接127.0.0.1的问题
  7. 如何提取抖音短视频中的音乐 1
  8. 如何学好C++,用好类库很重要
  9. 不知道怎么提取歌曲的伴奏?来看看这个简单的教程
  10. 手机端html展示pdf