cocos2dx的屏幕适配
1.版本
cocos3.9
2.屏幕适配
cocos有5种屏幕适配策略。
EXACT_ALL:非等比缩放,使画面充满整个屏幕,但会变形。
NO_BORDER:等比缩放,也会使画面充满整个屏幕,不会变形,但SS/DS比较大的一边刚好充满整个屏幕,而另一边就会超出屏幕,被截断。
SHOW_ALL:等比缩放,会让整个画面都显示出来,不会变形,不会截断,SS/DS比较小的一边刚好充满整个屏幕,而另一边往往会有黑边。
FIXED_HEIGHT:等比缩放,不会变形,高刚好充满整个屏幕,而宽可能有黑边也可能被截断。
FIXED_WIDTH:等比缩放,不会变形,宽刚好充满整个屏幕,而高可能有黑边也可能被截断。
5种适配策略效果如图所示:
cocos里面有四种尺寸概念,分别是VisibleSize,WinSize,FrameSize,DesignSize。
FrameSize:
指的是屏幕的实际分辨率,通过Director::getInstance()->getOpenGLView()->getFrameSize()
获取。在调试的时候可以通过Director::getInstance()->getOpenGLView()->setFrameSize()
来设置。
DesignSize:
指的是设计分辨率,通过Director::getInstance()->getOpenGLView()->setDesignResolutionSize
来设置。这个也是我们设置屏幕适配策略的手段。
setDesignResolutionSize
会调用updateDesignResolutionSize
来调整设计分辨率,
void GLView::updateDesignResolutionSize()
{if (_screenSize.width > 0 && _screenSize.height > 0&& _designResolutionSize.width > 0 && _designResolutionSize.height > 0){_scaleX = (float)_screenSize.width / _designResolutionSize.width;_scaleY = (float)_screenSize.height / _designResolutionSize.height;if (_resolutionPolicy == ResolutionPolicy::NO_BORDER){_scaleX = _scaleY = MAX(_scaleX, _scaleY);}else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL){_scaleX = _scaleY = MIN(_scaleX, _scaleY);}else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) {_scaleX = _scaleY;_designResolutionSize.width = ceilf(_screenSize.width/_scaleX);}else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {_scaleY = _scaleX;_designResolutionSize.height = ceilf(_screenSize.height/_scaleY);}// calculate the rect of viewportfloat viewPortW = _designResolutionSize.width * _scaleX;float viewPortH = _designResolutionSize.height * _scaleY;_viewPortRect.setRect((_screenSize.width - viewPortW) / 2, (_screenSize.height - viewPortH) / 2, viewPortW, viewPortH);// reset director's member variables to fit visible rectauto director = Director::getInstance();director->_winSizeInPoints = getDesignResolutionSize();director->createStatsLabel();director->setGLDefaultValues();}
}
由代码可以看到除了FIXED_HEIGHT和FIXED_WIDTH外其他策略都没有调整设计分辨率的大小。
WinSize:
指的是OpenGL视口转化到设计分辨率下的尺寸,通俗的讲就是OpenGL画布在我们设计世界的大小,它实际上是经过引擎调整后的设计尺寸。
const Size& Director::getWinSize(void) const
{return _winSizeInPoints;
}
void GLView::updateDesignResolutionSize()
{...// reset director's member variables to fit visible rectauto director = Director::getInstance();director->_winSizeInPoints = getDesignResolutionSize(); //将DesignSize赋值给WinSizedirector->createStatsLabel();director->setGLDefaultValues();}
}
VisibleSize:
指的是OpenGL视口转化到设计分辨率下我们可以看到的最大区域的大小。并不是说OpenGL的画布有多大我们就可以看到多大,它有可能超出屏幕外。所以VisibleSize总是小于等于DesignSize。
其实也就是说只要你用大小等于VisibleSize的图片,它就能把整个游戏画面填满。(填满不是指没有黑边,黑边有两种情况,一种是在VisibleSize的范围内,但因为在黑边的范围内没有渲染元素,所以才显示黑色,如果你的图片足够大,是不会有黑边的,如FIXED_HEIGHT和FIXED_WIDTH。另一种是超出了VisibleSize的范围,如SHOW_ALL,在这种情况下就算在这个范围里有渲染元素,它显示出来也是黑边,因为超出了OpenGL画布的范围。)
Size Director::getVisibleSize() const
{if (_openGLView){return _openGLView->getVisibleSize();}else{return Size::ZERO;}
}
Size GLView::getVisibleSize() const
{if (_resolutionPolicy == ResolutionPolicy::NO_BORDER){return Size(_screenSize.width/_scaleX, _screenSize.height/_scaleY);}else {return _designResolutionSize;}
}
void GLView::updateDesignResolutionSize()
{if (_screenSize.width > 0 && _screenSize.height > 0&& _designResolutionSize.width > 0 && _designResolutionSize.height > 0){_scaleX = (float)_screenSize.width / _designResolutionSize.width;_scaleY = (float)_screenSize.height / _designResolutionSize.height;if (_resolutionPolicy == ResolutionPolicy::NO_BORDER){_scaleX = _scaleY = MAX(_scaleX, _scaleY);}...
结合上面的三个代码也能印证VisibleSize≤DesignSize
的猜测。
3.视口和投影矩阵的设置
3.1.视口设置
cocos会用WinSize来设置OpenGL视口的大小。cocos内部又会把它转换成现实尺寸的大小。
void Director::setViewport()
{if (_openGLView){_openGLView->setViewPortInPoints(0, 0, _winSizeInPoints.width, _winSizeInPoints.height);}
}
void GLView::setViewPortInPoints(float x , float y , float w , float h)
{glViewport((GLint)(x * _scaleX + _viewPortRect.origin.x),(GLint)(y * _scaleY + _viewPortRect.origin.y),(GLsizei)(w * _scaleX),(GLsizei)(h * _scaleY));
}
3.2.投影矩阵设置
cocos还会用WinSize来设置投影矩阵。
void Director::setProjection(Projection projection)
{Size size = _winSizeInPoints;setViewport();switch (projection){...case Projection::_3D:{float zeye = this->getZEye();Mat4 matrixPerspective, matrixLookup;loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);#if CC_TARGET_PLATFORM == CC_PLATFORM_WP8//if needed, we need to add a rotation for Landscape orientations on Windows Phone 8 since it is always in Portrait ModeGLView* view = getOpenGLView();if(getOpenGLView() != nullptr){multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, getOpenGLView()->getOrientationMatrix());}
#endif// issue #1334Mat4::createPerspective(60, (GLfloat)size.width/size.height, 10, zeye+size.height/2, &matrixPerspective);multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixPerspective);Vec3 eye(size.width/2, size.height/2, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);Mat4::createLookAt(eye, center, up, &matrixLookup);multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixLookup);loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);break;}case Projection::CUSTOM:// Projection Delegate is no longer needed// since the event "PROJECTION CHANGED" is emittedbreak;default:CCLOG("cocos2d: Director: unrecognized projection");break;}_projection = projection;GL::setProjectionMatrixDirty();_eventDispatcher->dispatchEvent(_eventProjectionChanged);
}
4.可视区域原点
通过上面那张适配策略效果图,我们可以知道世界左边的原点其实不一定是在屏幕的左下角,而可视区域的原点除了NO_BORDER外都是(0,0),它的原点可以通过Director::getInstance()->getVisibleOrigin()
获取。如果我们希望一张图片不论什么屏幕都显示在屏幕的正中间那么可以这么做,
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
一句话,NO_BORDER,FIXED_HEIGHT,FIXED_WIDTH需要做位置的调整,SHOW_ALL、EXACT_FIT不用。
此文章只是我学习过程中用来记录自己的理解,可作参考,可能有错误。
cocos2dx的屏幕适配相关推荐
- cocos2d-x lua 屏幕适配
转载请注明原文地址:https://segmentfault.com/a/1190000000635287 研究了两天屏幕适配,了解了Cocos提供的屏幕适配的方案有下面几种: 1, EXACT_FI ...
- Cocos2d-x 屏幕适配新解
原文链接(http://blog.leafsoar.com/archives/2013/05-10-19.html),作者一叶. 为了适应移动终端的各种分辨率大小,各种屏幕宽高比,在 cocos2d- ...
- Cocos2d-x 屏幕适配新解(比较全面比较详细)
黑米GameDev街区 『 不要让任何事情成为你不去学习的理由!』 -Himi Home About Himi Himi's Book 街区须知 资源/技术群 订阅本站 主页 > Cocos2d ...
- cocos2d 屏幕適配_cocos2d-x 屏幕适配新解
转自:http://blog.leafsoar.com/archives/2013/05-10-19.html 为了适应移动终端的各种分辨率大小,各种屏幕宽高比,在 cocos2d-x(当前稳定版:2 ...
- cocos2dx基础篇(29)——屏幕适配
[唠叨] 手机的屏幕大小千差万别,如现在流行的安卓手机屏幕大部分长宽比例为16:9.而iPhone 5S的长宽比例为71:40(接近16:9),也有预测说iPhone 6S的长宽比例也将会是主流的16 ...
- cocos2dx 屏幕适配
别较真,不是真正的屏幕适配,只是让在一套设计下,在各个屏幕分辨率下都能凑合看,也是比较省事快速偷懒的一种办法,只要能接受~~ 不足之处就是吧,和设计分辨率不匹配的屏幕下,会有黑边 修改代码AppDel ...
- cocos2d-x屏幕适配原理
原文地址:http://m.blog.csdn.net/article/details?id=50827766 一.适配简介 如今市面上的手机种类越来越多,分辨率是千变万化的.但是我们做游戏开发,喜欢 ...
- Cocos2d-x 屏幕适配
为了适应移动终端的各种分辨率大小,各种屏幕宽高比,在 cocos2d-x(当前稳定版:2.0.4) 中,提供了相应的解决方案,以方便我们在设计游戏时,能够更好的适应不同的环境. 而在设计游戏之初,决定 ...
- Cocos2d-x之多分辨率屏幕适配
一.适配简介 如今市面上的手机种类越来越多,分辨率是千变万化的.但是我们做游戏开发,喜欢自己的游戏可以在各个手机都能合适的运行,那么就需要做多分辨率的适配. 二.retain屏幕概念 之前,苹果手机对 ...
最新文章
- QT5生成可执行文件总结
- 不会用计算机怎么办,不会看电脑配置怎么办?通过本文就可以详细了解电脑配置信息...
- 我用AI回怼美女汽车销售系列[yolo车牌识别](四)
- WebApi网关之Bumblebee和Ocelot性能对比
- Source Insight之Relation Window Properties配置和一些快捷键
- python自动关闭弹窗_python – 每隔x分钟创建一个tkinter窗口,然后在y秒后自动关闭它...
- 一文搞懂Python知识难点------装饰器
- arraylist删除指定元素_【追凶】ArrayList使用增强for遍历删除元素异常ConcurrentModification...
- 读入字符串/字符 scanf与getchar/gets区别
- 二叉树的遍历实验报告C语言,二叉树的建立与遍历实验报告(c语言编写,附源代码)...
- 带经纬度的水印相机_这个国庆节,元道经纬相机做交警人员的好帮手
- P1164 小A点菜(动态规划背包问题)
- 如何成为Emacs高手,像神一样使用编辑器
- 2021-09-02最大矩形
- 修改表字段长度的操作,对业务是否有影响?
- 详解网易有道AI战略,智能硬件、教育、办公三大解决方案
- onenote2016下载地址
- 微软的SqlHelper做数据层(一)
- CVPR 2022 | 谷歌提出mip-NeRF 360:全景NeRF越来越丝滑!
- 被国家地理认可的业余摄影师拍摄指南