[cocos2dx]屏幕適配

由於各種智能手機的屏幕大小都不一致,會出現同一張圖片資源在不同的設備分辨率下顯示不一樣的問題。爲避免這樣的情況,需要Cocos引擎能提供多分辨率的支持,也就是說要求實現這樣的效果 — 開發者不需要考慮程序實際運行在什麼分辨率下而只需要制定設置好設計分辨率就行,接着引擎便會自動實現設計分辨率(DesignSize)到屏幕分辨率(FrameSize)的轉化,以及不同資源分辨率到設計分辨率的轉化。

1.在適配過程中必須明確幾個概念:

Frame大小:這個值在windows/mac/linux下就是創建窗體的大小,在手機上就是屏幕大小。

設置方式:這裏我們設置一個全局的變量(這個是iphone5/5s的分辨率)。

static cocos2d::Size g_frame_size = cocos2d::Size(1136, 640);

auto director = Director::getInstance();

auto glview = director->getOpenGLView();

if(!glview) {

#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)

glview = GLViewImpl::createWithRect("ScreenFix", Rect(0, 0, g_frame_size.width, g_frame_size.height)); //這裏設置窗體大小

#else

glview = GLViewImpl::create("ScreenFix"); //這裏就是手機屏幕大小

#endif

director->setOpenGLView(glview);

}

獲取方式:

Size cur_frame_size = Director::getInstance()->getOpenGLView()->getFrameSize();

Design分辨率大小:邏輯設計分辨率大小,美術可以根據這個設計分辨率來設計資源大小以及UI佈局。會根據不同的分辨率適配策略,按Frame和Design的某種比例進行縮放。

設置方式:這裏我們設置一個全局的變量(這個是比較常用的分辨率),後面將不斷修改分辨率策略對畫面整體的影響。

static cocos2d::Size g_design_resolution_size = cocos2d::Size(960, 640);

glview->setDesignResolutionSize(g_design_resolution_size.width, g_design_resolution_size.height, ResolutionPolicy::EXACT_FIT); //這裏設置分辨率策略

獲取方式:(注意:修改分辨率策略,獲得的設計分辨率將不一樣!!!)

Size cur_design_size = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();

VisibleSize:可視區域大小,一般情況下UI都要在可視範圍內,根據這個值可以對UI進行位置的適配。

獲取方式:

 Size cur_visible_size = Director::getInstance()->getOpenGLView()->getVisibleSize();

VisibleOrigin:可視區域原點位置,用於可視區域位置的計算。

獲取方式:

Vec2 cur_origin = Director::getInstance()->getOpenGLView()->getVisibleOrigin();

一 設計分辨率

顧名思義,指由開發者自定義的分辨率,最終引擎會拿實際的屏幕分辨率和這個自定義的設計分辨率得到縮放因子。但實際的項目開發中還有細節要兼顧,如是否需要寬高都等比縮放,故有一知識點—縮放策略。在cocos2dx中通過setDesignResolutionSize來設置,方法使用如下:

setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);

參數width和height指定設計分辨率的尺寸,resolutionPolicy指定縮放策略,由ResolutionPolicy枚舉定義,如下圖所示:

//Cocos2dConstants.lua

cc.ResolutionPolicy =

{

EXACT_FIT = 0,

NO_BORDER = 1,

SHOW_ALL = 2,

FIXED_HEIGHT = 3,

FIXED_WIDTH = 4,

UNKNOWN = 5,

}

  • EXACT_FIT :充滿整個屏幕,唯一一個不按等比縮放的策略寬高比不相等可能導致拉伸或壓縮發生形變,一般情況下不使用;
  • NO_BORDER :充滿屏幕,等比縮放實質上是屏幕寬、高分別和設計分辨率寬、高計算縮放因子,取較()者作爲寬、高的縮放因子。保證了設計區域總能一個方向上鋪滿屏幕,而另一個方向一般會超出屏幕區域。 而區域是被居中對齊到屏幕(如上圖);
  • SHOW_ALL:保持全部元素可見,等比縮放實質是屏幕寬、高分別和設計分辨率寬、高計算縮放因子,取較()者作爲寬、高的縮放因子。保證了設計區域全部顯示到屏幕上,但可能會有黑邊(如上圖)。
  •   以上三者都不需要開發者對元素的位置進行調整,都是優先字面上的意思,NO_BORDER是“沒黑邊,但可能有裁剪”,SHOW_ALL是“完全沒裁剪,但可能有黑邊”,可以說兩者剛好是相反的情況。
  • FIXED_HEIGHT:也是等比縮放按照 窗體(手機)分辨率高度/設計分辨率高度 的比例,縮放設計分辨率畫面。這種設計分辨率,適合於橫版遊戲。美術出底圖資源時,要保證寬度足夠,否則會穿幫。它使用屏幕左下角作爲原點。
  • FIXED_WIDTH:也是等比縮放按照 窗體(手機)分辨率寬度/設計分辨率寬度 的比例,縮放設計分辨率畫面。這種設計分辨率,適合於豎版遊戲。美術出底圖資源時,要保證高度足夠,否則會穿幫。它使用屏幕左下角作爲原點。

 二 調整元素位置

  除了FIXED_XXXX,其他的縮放策略的繪製區域都是設計分辨率表示的有效區域,都是設計分辨率對應區域的原點。但是FIXED_XXXX對應的區域改變了,則程序中設定的絕對座標往往失效,如下圖的在一個分辨率中位於中點的點(100,50),在另一分辨率下就不再是中點了:

  

故針對使用FIXED_XXXX縮放策略的項目,開發過程中儘量不要使用絕對座標,除此以外別的策略都沒有問題。解決這個問題的方法是不固定邊方向的座標不要用絕對座標,可以通過引入visibleSize輔助調整,如auto p2 = Vec2(visibleSize.width/2 - 10,visibleSize.height/2 + 3),這樣便可實現邏輯對齊的自適應了。

三 視口設置

ViewPort的設置在OpenGL的GPU渲染管線中的屏幕映射佔重要作用,在Cocos2dx中通過setViewPortInPoints方法來設置視口的大小:

void Director::setViewport()
{
    if (_openGLView)
    {
        _openGLView->setViewPortInPoints(0, 0, _winSizeInPoints.width, _winSizeInPoints.height);
    }
}

//CCGLView.cpp
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));
}

setViewPortInPoints方法將基於設計分辨率的座標信息轉換爲基於屏幕實際像素大小的座標信息,然後使用GL指令glViewPort進行設置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章