轉(zhuǎn)載自:http://blog.leafsoar.com/archives/2013/05-10.html
為了適應(yīng)移動(dòng)終端的各種分辨率大小,各種屏幕寬高比,在 cocos2d-x(當(dāng)前穩(wěn)定版:2.0.4) 中,提供了相應(yīng)的解決方案,以方便我們?cè)谠O(shè)計(jì)游戲時(shí),能夠更好的適應(yīng)不同的環(huán)境。
而在設(shè)計(jì)游戲之初,決定著我們屏幕適配的因素有哪些,簡(jiǎn)而言之只有兩點(diǎn):屏幕大小 和 寬高比。這兩個(gè)因素是如何影響游戲的:
- 屏幕大小: 從小分辨率 480x320 到 1280x800 分辨率,再到全高清 1080p,從手機(jī)到平板,還有蘋(píng)果設(shè)備的 Retina 屏,這么多不同的分辨率,而且大小差距甚大,不可能做到一套資源走天下,資源往小了設(shè)計(jì),在大屏幕會(huì)顯示模糊,圖片往大了設(shè)計(jì),在小屏幕設(shè)備又太浪費(fèi),而且小屏幕的手機(jī)硬件資源也會(huì)相對(duì)的緊缺,所以 根據(jù)屏幕大小使用不同的資源 是有必要的,而 cocos2d-x 也幫我們解決了這一點(diǎn)。
- 寬高比: 什么是寬高比,就是你的屏幕是方的還是長(zhǎng)的,靠近方形的分辨率如 480x320,比例為3:2,還有 960x540 的 16:9 標(biāo)準(zhǔn)寬屏,這也算是兩種總極端情況了,如果能在這兩種比例情況做好適配基本就可以了,如果比 3:2 “更方”如 4:3,比 16:9 “更長(zhǎng)”,那么不論如何布局,顯示效果差距甚大,最好對(duì)固定比例優(yōu)化吧。當(dāng)在寬高比在一定范圍內(nèi),可以通過(guò)靈活編寫(xiě)程序去適應(yīng),而在顯示效果上,cocos2d-x 為我們提供了三種模式,這些 模式更多的是幫我們解決比例不一的情況而存在 的,如果只是屏幕大小(比例一樣),那通過(guò)簡(jiǎn)單的放大縮小即可完成。
三種模式
說(shuō)是三種模式,其實(shí)還有一種 無(wú)模式,也就是 cocos2d-x 默認(rèn)的適配方案,現(xiàn)在我們就來(lái)認(rèn)識(shí)一下這些模式,并且通過(guò)這些模式去認(rèn)識(shí)其中一些概念 FrameSize、WinSize、VisibleSize、VisibleOrigin,以及它們存在的意義,并且最后靈活運(yùn)行這些概念 創(chuàng)建出一個(gè)不屬于這些模式而超越這些模式的新適配解決方案,這是最終目的。
kResolutionUnKnown 認(rèn)識(shí) FrameSize
這是 cocos2d-x 編寫(xiě)的默認(rèn)模式,沒(méi)有做任何處理,在這種情況下,游戲畫(huà)面的大小與比例都是不可控的,在程序運(yùn)行之初,由各個(gè)平臺(tái)入口函數(shù)定義畫(huà)面大小:
/ proj.linux/main.cpp linux 平臺(tái)手動(dòng)指定畫(huà)面大小
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
eglView->setFrameSize(720, 480);
// proj.android/jni/hellocpp/main.cpp android 平臺(tái)由 jni 調(diào)用傳入設(shè)備分辨率參數(shù)
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h)
{
if (!CCDirector::sharedDirector()->getOpenGLView())
{
CCEGLView *view = CCEGLView::sharedOpenGLView();
view->setFrameSize(w, h);
AppDelegate *pAppDelegate =
new AppDelegate();
CCApplication::sharedApplication()->run();
}
else {
// other

}
}
在此我們首先認(rèn)識(shí)了 FrameSize 參數(shù),在游戲運(yùn)行時(shí),我們可以通過(guò) CCEGLView::sharedOpenGLView()->getFrameSize();
獲得此值。如果在手機(jī)上運(yùn)行,那么不同分辨率將會(huì)得到不同的值,既然這個(gè)值不可控,那么在寫(xiě)游戲中也就沒(méi)有參考價(jià)值了,比如我們寫(xiě)一個(gè)精靈的位置距離底部 320 高度,在 480x320 分辨率,能看到其在屏幕上方,如果換一臺(tái)手機(jī)分辨率 960x540 那么只能顯示在中間靠上的位置,如果設(shè)置精靈位置為距離屏幕上方(高度)320,反之依然,顯示效果不一。
此時(shí)可行的方案是使用百分比,如精靈位置在屏幕橫向距離左邊 1/3 寬度,在 ½ 正中間處,而類(lèi)似這樣的設(shè)置也不用依賴(lài) FrameSize 的具體數(shù)值。而這樣的做法,使得內(nèi)部元素像彈簧一樣,隨著 FrameSize 的大小改變而改變,伸縮或者擠壓,對(duì)于圖片資源大小也是完全不可控,如果根據(jù)屏幕大小放大縮小,那我們可以考慮用下面要說(shuō)的模式,在此不推薦使用 cocos2d-x 的無(wú)模式方案。
kResolutionExactFit and kResolutionShowAll 認(rèn)識(shí) WinSize
在 AppDelegate.cpp 處可以通過(guò)設(shè)置:
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(720, 480, kResolutionShowAll);
// 或者
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(720, 480, kResolutionExactFit);
DesignResolutionSize!顧名思義,也就是邏輯上的游戲屏幕大小,在這里我們?cè)O(shè)置了其分辨率為 720x480 為例,那么在游戲中,我么設(shè)置精靈的位置便可以參照此值,如 左下角 ccp(0,0),右上角 ccp(720, 480),而不論 FrameSize 的大小為多少,是 720x480 也好,是 480x320 也罷,總能正確顯示其位置,左下角和右上角。能夠?qū)崿F(xiàn)這一點(diǎn)的原因是,固定了設(shè)計(jì)分辨率大小,從而確定了其固定的寬高比,它的 優(yōu)勢(shì) 是可以使用具體的數(shù)值擺放精靈位置,不會(huì)因?yàn)閷?shí)際屏幕大小寬高比而是內(nèi)部元素相對(duì)位置關(guān)系出現(xiàn)混亂。
而為了保持畫(huà)面的寬高比,cocos2d-x 做了些犧牲,犧牲了什么呢?kResolutionExactFit 犧牲了畫(huà)質(zhì)而保持了全屏顯示,對(duì)畫(huà)面進(jìn)行了拉伸,這意味著什么?意味著相對(duì)極端情況下,本來(lái)精靈是方形的,顯示出來(lái)變成長(zhǎng)方形,本來(lái)圓形的變成了橢圓,固此模式不推薦使用。kResolutionShowAll 為了保持設(shè)計(jì)畫(huà)面比例對(duì)四周進(jìn)行留黑邊處理,使得不同比例下畫(huà)面不能全屏。魚(yú)和熊掌不能兼得也 ~
我們可以通過(guò)如下方法獲取到 setDesignResolutionSize 所設(shè)置的值:
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
我們可以用 Cocos2d-x 程序是如何開(kāi)始運(yùn)行與結(jié)束的 一文的方法,跟蹤 WinSize 的初始化,獲取過(guò)程,在這里簡(jiǎn)單提一下,如下步驟:
// 獲得 winSize
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
// 查看其 getWinSize(); 方法實(shí)現(xiàn)
[cocos2dx-path]/cocos2dx/CCDirector.cpp
CCSize CCDirector::getWinSize(
void)
{
return m_obWinSizeInPoints;
}
// 而 m_obWinSizeInPoints 是何時(shí)被賦值的
[cocos2dx-path]/cocos2dx/platform/CCEGLViewProtocol.cpp
void CCEGLViewProtocol::setDesignResolutionSize(
float width,
float height, ResolutionPolicy resolutionPolicy)
{

m_obDesignResolutionSize.setSize(width, height);

CCDirector::sharedDirector()->m_obWinSizeInPoints = getDesignResolutionSize();
}
const CCSize& CCEGLViewProtocol::getDesignResolutionSize()
const{
return m_obDesignResolutionSize;
}
具體的優(yōu)勢(shì):通過(guò)設(shè)置邏輯分辨率大小,相比無(wú)模式,可以幫我們解決了屏幕自動(dòng)放大縮小問(wèn)題,并且保持屏幕寬高比,使得游戲更好設(shè)計(jì),可以將設(shè)計(jì)畫(huà)面大小作為默認(rèn)背景圖片大小等,唯一點(diǎn)遺憾就是那點(diǎn)前面所提到的一點(diǎn)點(diǎn)犧牲。
kResolutionShowAll 方案可以作為我們的默認(rèn)解決方案,使得游戲的設(shè)計(jì)更為簡(jiǎn)化,但為了補(bǔ)填拉伸或留黑邊這點(diǎn)缺憾,進(jìn)入下一個(gè)模式!
kResolutionNoBorder 了解 VisibleSize 與 VisibleOrigin
此模式可以解決兩個(gè)問(wèn)題,其一:游戲畫(huà)面全屏;其二:保持設(shè)置游戲時(shí)的寬高比例,相比 kResolutionShowAll 有所區(qū)別的是,為了填補(bǔ)留下的黑邊,將畫(huà)面稍微放大,以至于能夠正好補(bǔ)齊黑邊,而這樣做的后果可想而知,補(bǔ)齊黑邊的同時(shí),另一個(gè)方向上將會(huì)有一部分畫(huà)面露出屏幕之外,如下示意圖:

黑色邊框標(biāo)示實(shí)際的屏幕分辨率,紫色區(qū)域標(biāo)示游戲設(shè)計(jì)大小,而通過(guò)放大縮小,保持寬高比固定, 可以看到 Show All 之中的黑色陰影部分為留邊,而 No Border 的紫色陰影部分則不能顯示,而這紫色區(qū)域的大小是游戲設(shè)計(jì)之時(shí)是不可控的。那么原設(shè)計(jì)的畫(huà)面大小就失去了 一定的 參考價(jià)值了,因?yàn)檫@可能讓你的畫(huà)面顯示殘缺。這時(shí)僅僅通過(guò) WinSize 滿(mǎn)足不了我們的設(shè)計(jì)需求,所以引入了 VisibleSize 與VisibleOrigin 概念。

如上所示,紫色區(qū)域是被屏幕截去的部分,不可顯示的,根據(jù)實(shí)際情況,可能出現(xiàn)橫向截取和豎向截取,這取決于實(shí)際分辨率的寬高比。而 A、B、C、D所標(biāo)示的是設(shè)計(jì)分辨率,固定大小。如果我們想讓一個(gè)精靈元素顯示在屏幕上方靠邊,那么如果使用 WinSize 的高度設(shè)置其位置,可能出現(xiàn)的情況就是顯示到屏幕之外了。FrameSize 和 WinSize 我們已經(jīng)知道其概念,而 VisibleSize 和 VisibleOrigin 所代表的是什么呢,又時(shí)如何為我們解決靠邊的問(wèn)題!注意上圖下方的定義, VisibleSize = H I J K 是用紫色標(biāo)注的。而在上圖是 黑色 標(biāo)注,標(biāo)示屏幕實(shí)際分辨率,雖然 FrameSize 和 VisibleSize 都是 H I J K,但其意義不同,紫色表明它是與設(shè)計(jì)分辨率相關(guān)的。
FrameSize 是實(shí)際的屏幕分辨率,而 VisibleSize 是在 WinSize 之內(nèi),保持 FrameSize 的寬高比所能占用的最大區(qū)域,實(shí)際屏幕分辨率 H I J K (黑色) 可以大于 WinSize ,但VisibleSize 一定會(huì)小于或者等于 WinSize,這兩者相同的是寬高比。VisibleSize 有著 WinSize 大小(隨WinSize 的大小改變而改變),還有著 FrameSize 的寬高比,它標(biāo)示 在設(shè)計(jì)分辨率(WinSize)下,在屏幕中的可見(jiàn)區(qū)域大小。而 VisibleOrigin 則標(biāo)示在設(shè)計(jì)分辨率下被截取的區(qū)域大小,用點(diǎn) K 標(biāo)示,有了這些數(shù)據(jù),我們想讓游戲元素始終在屏幕顯示的區(qū)域之內(nèi)不成難事。下面通過(guò)幾個(gè)數(shù)值帶入,加深這些概念的印象。
// 組[1] :
FrameSize: width = 720, height = 420
WinSize: width = 720, height = 480
VisibleSize: width = 720, height = 420
VisibleOrigin: x = 0, y = 30
// 組[2] :相比 組 [1] FrameSize 不變 VisibleSize 和 VisibleOrigin 隨著 WinSize 的變小而變小
FrameSize: width = 720, height = 420
WinSize: width = 480, height = 320
VisibleSize: width = 480, height = 280
VisibleOrigin: x = 0, y = 20
// 組[3] : 相比組 [1] WinSize 不變,VisibleSize 隨著 FrameSize 的比例改變而改變
FrameSize: width = 720, height = 540
WinSize: width = 720, height = 480
VisibleSize: width = 640, height = 480
VisibleOrigin: x = 40, y = 0
// WinSize VisibleSize VisibleOrigin 與都設(shè)計(jì)的分辨率相關(guān),滿(mǎn)足如下關(guān)系
WinSize.width = (VisibleOrigin.x * 2) + VisibleSize.width
WinSize.height = (VisibleOrigin.y * 2) + VisibleSize.height
NoBorder 具體的使用方法可以參考 cocos2d-x 自帶例程 TestCpp ,有詳細(xì)的使用方法,并且封裝了VisibleRect 類(lèi),可以獲取設(shè)計(jì)分辨率,不同比例屏幕之時(shí)的主要參考點(diǎn),屏幕四個(gè)拐角,和邊的中點(diǎn)等,讓我們?cè)O(shè)置元素位置時(shí),使其總能顯示在屏幕之內(nèi),這里就不詳細(xì)介紹了。
基于這幾種模式的程序使用方法,cocos2d-x 自帶例程或者網(wǎng)上有很多教程,這里只詳細(xì)解釋了其中各種概念,而知道了這些概念,當(dāng)然用起來(lái)就沒(méi)有多大問(wèn)題了。
kResolutionLeafsoar
!!!這是什么模式!好吧,Leafsoar 是 一葉 的 ID ,或者是本博客的一級(jí)域名而已 :P 在 cocos2d-x 中并沒(méi)有這種模式。除卻 UnKnown 與 ExactFit 不說(shuō),ShowAll 的優(yōu)勢(shì)是,只需要一個(gè)設(shè)計(jì)分辨率,然后通過(guò) WinSize 設(shè)置相對(duì)對(duì)位即可,而且位置的最大長(zhǎng)寬都是確定,方便了開(kāi)發(fā),但屏幕不能填滿(mǎn), NoBorder 模式的優(yōu)勢(shì)是在畫(huà)面不變形的情況下,實(shí)現(xiàn)全屏,顯示效果更好,但 WinSize 一定程度失效,需要通過(guò)運(yùn)行時(shí)計(jì)算 VisibleSize 和 VisibleOrigin 來(lái)設(shè)置位置,由于是運(yùn)行時(shí)計(jì)算,所以也就會(huì)出現(xiàn),各種屏幕顯示效果不一樣的情況。
ShowAll 和 NoBorder 各有所長(zhǎng),各有所短,而這里提出的新適配解決方案正是取兩者之長(zhǎng),舍兩者之短的 組合模式。簡(jiǎn)單說(shuō)來(lái)就是用 NoBorder 去實(shí)現(xiàn) ShowAll 的思想。NoBorder 可以保證全屏利用,ShowAll 可以更好的使用實(shí)際設(shè)計(jì)坐標(biāo)固定位置,而且相對(duì)位置不會(huì)隨寬高比的改變而改變,這在編寫(xiě)游戲的時(shí)候能方便不少。先上一個(gè)示意圖,一目了然 (兩個(gè)圖,兩個(gè)方向):

在原來(lái) NoBorder 模式示意圖上添加了新的概念,LsSize = X Y M N (leafsoar 簡(jiǎn)寫(xiě)了,為了不跟 cocos2d-x 的一些概念混淆,什么名字不重要,只要了解其含義即可),在 NoBorder 模式下的 LsSize 相對(duì)于 FrameSize 而言,正如 在 ShowAll 模式下的 WinSize 相對(duì)于 FrameSize,所以說(shuō)這是 ShowAll NoBorder 的組合概念,而這里的 LsSize 與 WinSize 的寬高比是一致的。
猛地一看,似乎把問(wèn)題復(fù)雜化了,仔細(xì)一看,還不如猛地一看 ~~
在 ShowAll 中,WinSize 作為最高的寬高,以此參照設(shè)置位置,因?yàn)樵诖朔秶鷥?nèi)都能在屏幕上顯示,用了 NoBorder 使得四周可能被截去一塊區(qū)域,而這個(gè)區(qū)域大小不可控制,所以不能再使用 WinSize 作為參考點(diǎn)來(lái)設(shè)置位置,而這里的 LsSize 同樣,因?yàn)?LsSzie 不論在什么情況下,總能顯示在屏幕之內(nèi),我們可以方便的使用 LsSize 作為坐標(biāo)系參考,并且可以全屏顯示,在配合 VisibleSize ,相比純的 NoBorder 加強(qiáng)了不少。它可以怎么用?
可以把 LsSize 當(dāng)作 ShowAll 中的 WinSize 來(lái)用,而黑邊可以使用稍大的圖片填充,或者使用其它圖片修飾邊框,修飾的邊框圖案可大可小,可長(zhǎng)可短,填充屏幕,保持全屏。
開(kāi)始基于 LsSize 的游戲設(shè)計(jì)實(shí)現(xiàn)
為了能夠準(zhǔn)確實(shí)現(xiàn)基于 LsSize 的設(shè)計(jì),初步計(jì)劃將 LsSize 設(shè)定在 480x320 的分辨率方案,為此做了些準(zhǔn)備,首先不使用任何模式情況下,在場(chǎng)景內(nèi)調(diào)用如下:
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCPoint center = ccp(size.width/2, size.height/2);
// 大小 600x500 為了 NoBorder 看到效果,使用稍大的背景圖
CCSprite* pb = CCSprite::create("Back.jpg");
pb->setPosition(center);
this->addChild(pb, 0);
// 480x320 此圖為使用于設(shè)計(jì)分辨率 LsSize 的圖片
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(center);
this->addChild(pSprite, 0);
// 37x37 在 480x320 畫(huà)面的四個(gè)拐角處,添加參照
CCSprite* p1 = CCSprite::create("Peas.png");
p1->setPosition(ccpAdd(center, ccp(-240, -160)));
this->addChild(p1);
CCSprite* p2 = CCSprite::create("Peas.png");
p2->setPosition(ccpAdd(center, ccp(240, 160)));
this->addChild(p2);
CCSprite* p3 = CCSprite::create("Peas.png");
p3->setPosition(ccpAdd(center, ccp(-240, 160)));
this->addChild(p3);
CCSprite* p4 = CCSprite::create("Peas.png");
p4->setPosition(ccpAdd(center, ccp(240, -160)));
this->addChild(p4);
顯示效果:(FrameSize = 640x540) 
顯示效果:(ShowAll; FrameSize = 520x320; WinSize = 480x320) 
顯示效果:(NoBorder; FrameSize = 520x320; WinSize = 480x320) 
通過(guò)效果我們可以看到,在相同 FrameSize 下 NoBorder 時(shí),畫(huà)面由于填充了黑邊,將畫(huà)面放大,以至于上下有部分顯示不全,通過(guò)拐角四個(gè)精靈可以看出。
好!既然我們知道是由于放大所致,那么我們將畫(huà)面縮小呢?cocos2d-x 提供了一個(gè)方法,我們調(diào)用如下代碼:
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setContentScaleFactor(
CCEGLView::sharedOpenGLView()->getScaleY() );
為了彌補(bǔ)畫(huà)面因需要不填空白出現(xiàn)的方法,我們將畫(huà)面縮小,放大系數(shù)可以通過(guò)CCEGLView::sharedOpenGLView()–>getScaleY() 取得。其實(shí) setContentScaleFactor 方法是為了適配不同資源而設(shè)計(jì)的,可以用此方法對(duì)不同資源適配,縮放等。效果如下:

我們看到 480x320 的圖片顯示完全正確了,也正是我們想要的效果,但唯一的缺點(diǎn)是 ~~ 拐角處四個(gè)精靈的位置依然不是我們想要的,我們?cè)O(shè)計(jì)的位置是以 480x320 設(shè)置位置的,而 WinSize 也是 480x320 ,而此時(shí)基于 480x320 的設(shè)計(jì)必然會(huì)顯示到屏幕之外,而要想不修改精靈位置,而讓其顯示正確的位置,那么為了保證 LsSize 的固定,我們需要一個(gè)方法,那就是 動(dòng)態(tài)設(shè)置 WinSize。
什么意思?我們知道一般這些模式設(shè)計(jì)游戲時(shí),是通過(guò) setDesignResolutionSize 設(shè)置 WinSize 的,這個(gè)值在游戲運(yùn)行其間是定植,動(dòng)態(tài)改變的是 VisibleSize 等,而這里提出了 LsSize 的概念,可想而知,如果 WinSize 固定,那么 LsSize 會(huì)隨著屏幕寬高比的改變而改變,那么我們反其道而行,固定 LsSize值,那么在運(yùn)行時(shí)可以通過(guò)實(shí)際的寬高比來(lái)算得 WinSize 的值,這樣動(dòng)態(tài)算得的 WinSize 值就能夠保證我們的 LsSize 是一個(gè)定值了。
相對(duì)論,WinSize 與 LsSize 的值是相對(duì)的,與其通過(guò)固定 WinSize 在運(yùn)行時(shí)動(dòng)態(tài)獲得 LsSize (這也是 NoBorder 的默認(rèn)方式,而導(dǎo)致的結(jié)果是 WinSize 沒(méi)有參考價(jià)值),不如我們固定 LsSize 而在運(yùn)行時(shí)算得 WinSize 設(shè)置來(lái)的要更妙一些。
現(xiàn)在不使用 setContentScaleFactor 方法,而修改 setDesignResolutionSize 這里的值,我們知道 WinSize 是 480x320 時(shí),LsSize 必然會(huì)小于此值,而 NoBorder 的放大系數(shù)我們可以通過(guò)如下方式算得(可以參考setDesignResolutionSize方法內(nèi)部實(shí)現(xiàn)),并在 AppDelegate 里執(zhí)行:
CCSize frameSize = CCEGLView::sharedOpenGLView()->getFrameSize();
// 設(shè)置 LsSize 固定值
CCSize lsSize = CCSizeMake(480, 320);
float scaleX = (float) frameSize.width / lsSize.width;
float scaleY = (float) frameSize.height / lsSize.height;
// 定義 scale 變量
float scale = 0.0f; // MAX(scaleX, scaleY);
if (scaleX > scaleY) {
// 如果是 X 方向偏大,那么 scaleX 需要除以一個(gè)放大系數(shù),放大系數(shù)可以由樅方向獲取,
// 因?yàn)榇藭r(shí) FrameSize 和 LsSize 的上下邊是重疊的
scale = scaleX / (frameSize.height / (float) lsSize.height);
} else {
scale = scaleY / (frameSize.width / (float) lsSize.width);
}
CCLog("x: %f; y: %f; scale: %f", scaleX, scaleY, scale);
// 根據(jù) LsSize 和屏幕寬高比動(dòng)態(tài)設(shè)定 WinSize
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(lsSize.width * scale,
lsSize.height * scale, kResolutionNoBorder);
顯示效果:(NoBorder 模式 ;FrameSize = 520x320; LsSize = 480x320; WinSize = 動(dòng)態(tài)獲取) 
我們看到在沒(méi)有修改源代碼,并且在設(shè)計(jì)中使用 480x320 的參考系,也既是基于 LsSize 的設(shè)計(jì)顯示效果如我們預(yù)期,那么我們換一個(gè) FrameSize 來(lái)看看是否能夠自動(dòng)適應(yīng)呢?如下:
顯示效果:(NoBorder 模式 ;FrameSize = 600x480; LsSize = 480x320; WinSize = 動(dòng)態(tài)獲取) 
到此,基于 LsSize 參考系的游戲設(shè)計(jì)已經(jīng)完成了,這樣做的好處是很明顯的,集 ShowAll 和 NoBorder 的優(yōu)點(diǎn)于一處,這里的圖片元素是為了好定位,實(shí)現(xiàn)的需要而寫(xiě)的,具體場(chǎng)景可以使用背景地圖,或一張大的圖片顯示,而沒(méi)有任何影響,也可以繼續(xù)使用 VisibleSize 得到 LsSize 之外的部分區(qū)域大小,在 LsSize 之外可以使用背景圖片作為裝飾,即保證了游戲的全屏,又保證了游戲設(shè)計(jì)時(shí)的方便,如果使用完全基于 LsSize 的設(shè)計(jì)實(shí)現(xiàn),除了顯示背景裝飾之外,我們不想讓 LsSize 的內(nèi)部元素顯示到 LsSize 之外如何做呢?我們只需要設(shè)定 LsSize 層的的顯示區(qū)域即可,我們可以修改場(chǎng)景的實(shí)現(xiàn):
/ 這里先簡(jiǎn)單實(shí)現(xiàn)思路
CCScene* HelloWorld::scene() {
CCScene *scene = CCScene::create();
// 創(chuàng)建背景層
CCLayer* b = CCLayer::create();
scene->addChild(b);
// 添加背景圖片和設(shè)置位置,可以使用其它裝飾,或者小圖片屏幕都行
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCPoint center = ccp(size.width/2, size.height/2);
CCSprite* pb = CCSprite::create("Back.jpg");
pb->setPosition(center);
b->addChild(pb, 0);
// 創(chuàng)建 LsLayer 層
HelloWorld *lsLayer = HelloWorld::create();
scene->addChild(lsLayer);
return scene;
}
// 在 HelloWorld 中重寫(xiě) visit() 函數(shù) 設(shè)定顯示區(qū)域
void HelloWorld::visit() {
glEnable(GL_SCISSOR_TEST); // 開(kāi)啟顯示指定區(qū)域
// 在這里只寫(xiě)上固定值,在特性環(huán)境下,以便快速看效果,實(shí)際的值,需要根據(jù)實(shí)際情況算得
glScissor(20, 0, 480, 320); // 只顯示當(dāng)前窗口的區(qū)域
CCLayer::visit(); // 調(diào)用下面的方法
glDisable(GL_SCISSOR_TEST); // 禁用
}
顯示效果:(NoBorder 模式 ;FrameSize = 520x320; LsSize = 480x320; WinSize = 動(dòng)態(tài)獲取) 
屏幕適配新解
看完這篇文章想必對(duì) cocos2d-x 的屏幕適配方案及其原理有了相當(dāng)?shù)恼J(rèn)識(shí),從內(nèi)部提供的三種模式,再到我們自定義基于 LsSize 的 Leafsoar 模式 (好把,因該叫做 ShowAllNoBorder)。這里已經(jīng)給出了完全的實(shí)現(xiàn)原理以及實(shí)現(xiàn)方法,并配有效果圖,當(dāng)然這其中還有些細(xì)節(jié)需要注意,比如我們基于 LsSize 的大小設(shè)計(jì),那么實(shí)際的圖片肯定需要比 LsSize 的要大,大多少,太小了不夠適應(yīng),太大了又浪費(fèi),如何取舍等問(wèn)題,這一點(diǎn)取決的因素是什么,留給讀者思考 ~~
一葉將在 GitHub 處建立一個(gè)ScreenSolutions 項(xiàng)目,讀者可以從這里參考實(shí)現(xiàn)的方案。(也許此時(shí)在 GitHub 所看到的實(shí)現(xiàn)并不完全,但已經(jīng)有了簡(jiǎn)單的實(shí)現(xiàn)方法,并且能夠運(yùn)行,如有必要,將會(huì)新寫(xiě)一篇博客,去實(shí)現(xiàn) ScreenSolutions 并且解說(shuō))