Cocos2d-x屏幕适配

前端之家收集整理的这篇文章主要介绍了Cocos2d-x屏幕适配前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Cocos2d-x屏幕适配

资源分辨率,设计分辨率,屏幕分辨率

  • Resources width 以下简写为RW,Resources height 以下简写为RH
  • Design width 以下简写为DW,Design height 以下简写为DH
  • Screen width 以下简写为SW,Screen height 以下简写为SH


接口setContentScaleFactor()和setSearchPaths()控制着第一个转换过程。
而setDesignResolutionSize()控制第二个过程。两个过程结合在一起,影响最终的显示效果

从资源分辨率到设计分辨率

setSearchPaths()需要根据当前屏幕分辨率做恰当的设置。
setContentScaleFactor()决定了图片显示到屏幕的缩放因子,但是这个接口的参数不是通过资源图片的宽、高比屏幕宽、高得来。Cocos2d-x引擎设计试图屏蔽游戏开发者直接去关注屏幕,所以这个因子是资源宽、高比设计分辨率宽、高。
setContentScaleFactor()通常有两个方式来设置参数。 RH/DH或RW/DW,不同的因子选择有不同的缩放负作用。 先看一张图:

用高度比作为内容缩放因子,保证了背景资源的垂直方向在设计分辨率范围内的全部显示
用宽度比作为内容缩放因子,保证了背景资源的水平方向在设计分辨率范围内的全部显示

从设计分辨率到屏幕分辨率

首先,我们通过一张图了解下Cocos2d-X的几种屏幕适配规则:

1. EXACT_FIT将设计尺寸映射到屏幕尺寸,长宽按各自比例拉伸,可能造成图像拉伸变形。
2. SHOW_ALL和NO_BORDER都是长宽等比例拉伸,图像不会被拉伸变形;但可能造成黑边和资源显示不全的问题。
3. FIXED_HEIGHT和FIXED_WIDTH和之前的三种策略不同,EXACT_FIT、SHOW_ALL和NO_BORDER都不会修正设计尺寸,而FIXED_HEIGHT和FIXED_WIDTH在设计阶段就修正设计尺寸,让可视区域就是设计尺寸区域。
4. NO_BORDER是唯一可视区域小于最终设计区域(FIXED_HEIGHT和FIXED_WIDTH会修正传入的设计尺寸)的一种策略。其他几种策略的设计区域等于设计区域。
5. NO_BORDER、FIXED_HEIGHT和FIXED_WIDTH三种策略根据设计或可视区域的改变需要做相应的坐标适配。

FIXED_HEIGHT:
1. 如果屏幕尺寸长高比>资源尺寸长高比,进行坐标偏差纠正,让资源居中显示,左右两边留黑边。
2. 如果屏幕尺寸长高比<资源尺寸长高比,进行坐标偏差纠正,让资源居中显示,左右两边被裁剪无法显示

所以,屏幕尺寸长高比略小于资源尺寸长高比,显示效果最佳。

源码面前无秘密

  1. class CC_DLL GLView : public Ref
  2. {
  3. /** * Get the frame size of EGL view. * In general,it returns the screen size since the EGL view is a fullscreen view. * * @return The frame size of EGL view. */
  4. const Size& GLView::getFrameSize() const
  5. {
  6. return _screenSize;
  7. }
  8.  
  9. /** * Set the frame size of EGL view. * * @param width The width of the fram size. * @param height The height of the fram size. */
  10. void GLView::setFrameSize(float width,float height)
  11. {
  12. _screenSize = Size(width,height);
  13. }
  14. /** * Get the visible area size of opengl viewport. * * @return The visible area size of opengl viewport. */
  15. Size GLView::getVisibleSize() const
  16. {
  17. if (_resolutionPolicy == ResolutionPolicy::NO_BORDER)
  18. {
  19. return Size(_screenSize.width/_scaleX,_screenSize.height/_scaleY);
  20. }
  21. else
  22. {
  23. return _designResolutionSize;
  24. }
  25. }
  26.  
  27. /** * Get the visible origin point of opengl viewport. * * @return The visible origin point of opengl viewport. */
  28. Vec2 GLView::getVisibleOrigin() const
  29. {
  30. if (_resolutionPolicy == ResolutionPolicy::NO_BORDER)
  31. {
  32. return Vec2((_designResolutionSize.width - _screenSize.width/_scaleX)/2,(_designResolutionSize.height - _screenSize.height/_scaleY)/2);
  33. }
  34. else
  35. {
  36. return Vec2::ZERO;
  37. }
  38. }
  39. /** * Set the design resolution size. * @param width Design resolution width. * @param height Design resolution height. * @param resolutionPolicy The resolution policy desired,you may choose: * [1] EXACT_FIT Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio,your game view will be stretched. * [2] NO_BORDER Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio,two areas of your game view will be cut. * [3] SHOW_ALL Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio,two black borders will be shown. */
  40. void GLView::setDesignResolutionSize(float width,float height,ResolutionPolicy resolutionPolicy)
  41. {
  42. CCASSERT(resolutionPolicy != ResolutionPolicy::UNKNOWN,"should set resolutionPolicy");
  43.  
  44. if (width == 0.0f || height == 0.0f)
  45. {
  46. return;
  47. }
  48.  
  49. _designResolutionSize.setSize(width,height);
  50. _resolutionPolicy = resolutionPolicy;
  51.  
  52. updateDesignResolutionSize();
  53. }
  54.  
  55. void GLView::updateDesignResolutionSize()
  56. {
  57. if (_screenSize.width > 0 && _screenSize.height > 0
  58. && _designResolutionSize.width > 0 && _designResolutionSize.height > 0)
  59. {
  60. _scaleX = (float)_screenSize.width / _designResolutionSize.width;
  61. _scaleY = (float)_screenSize.height / _designResolutionSize.height;
  62.  
  63. if (_resolutionPolicy == ResolutionPolicy::NO_BORDER)
  64. {
  65. _scaleX = _scaleY = MAX(_scaleX,_scaleY);
  66. }
  67.  
  68. else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL)
  69. {
  70. _scaleX = _scaleY = MIN(_scaleX,_scaleY);
  71. }
  72.  
  73. else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) {
  74. _scaleX = _scaleY;
  75. _designResolutionSize.width = ceilf(_screenSize.width/_scaleX);
  76. }
  77.  
  78. else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {
  79. _scaleY = _scaleX;
  80. _designResolutionSize.height = ceilf(_screenSize.height/_scaleY);
  81. }
  82.  
  83. // calculate the rect of viewport
  84. float viewPortW = _designResolutionSize.width * _scaleX;
  85. float viewPortH = _designResolutionSize.height * _scaleY;
  86.  
  87. _viewPortRect.setRect((_screenSize.width - viewPortW) / 2,(_screenSize.height - viewPortH) / 2,viewPortW,viewPortH);
  88.  
  89.  
  90. // reset director's member variables to fit visible rect
  91. auto director = Director::getInstance();
  92. director->_winSizeInPoints = getDesignResolutionSize();
  93. director->_isStatusLabelUpdated = true;
  94. director->setProjection(director->getProjection());
  95.  
  96. // Github issue #16139
  97. // A default viewport is needed in order to display the FPS,
  98. // since the FPS are rendered in the Director,and there is no viewport there.
  99. // Everything,including the FPS should renderer in the Scene.
  100. glViewport(0,0,_screenSize.width,_screenSize.height);
  101. }
  102. }
  103.  
  104. };

设置/获取屏幕的大小(主要是desktop系统上设置,也用于调试各屏幕适配的情况是否符合我们的预期等):
void GLView:: setFrameSize(float width,float height)
const Size& GLView::getFrameSize() const

设置/获取设计尺寸大小(相当于我们设定了我们的创作区域大小、最终如何显示到屏幕上,通过ResolutionPolicy指定。
注意:SHOW_ALL、EXACT_FIT、NO_BORDER三种策略的设计分辨率都是传入值,内部不做修正。FIXED_HEIGHT和FIXED_WIDTH都是会在内部修正传入设计分辨率,以保证屏幕分辨率到设计分辨率无拉伸铺满屏幕,所以通过getDesignResolutionSize()获取的值可能与传入的值不一致。
void GLView:: setDesignResolutionSize(float width,float height,ResolutionPolicy resolutionPolicy)
const Size& GLView::getDesignResolutionSize() const

获取可视区域的大小和原点,即我们设定的setDesignResolutionSize大小有多少是可以被显示的。由于适配策略NO_BORDER,有可能设计区域有部分最终无法在屏幕上显示,所以这里需要计算,可视原点也可能不是(0,0)。还有由于我们通过setDesignResolutionSize设置的设计尺寸大小,FIXED_HEIGHT、FIXED_WIDTH因为需要裁剪,所以这里的可视区域大小也是经过裁剪后的大小。
Size GLView::getVisibleSize() const
Vec2 Director::getVisibleOrigin() const

这里获取的WinSize,即setDesignResolutionSize设置后经过计算裁剪(可能)的_designResolutionSize。 const Size& Director::getWinSize(void) const

猜你在找的Cocos2d-x相关文章