Cocos2d-x——Cocos2d-x 屏幕適配新解 – 兼容與擴展【轉載】

Cocos2d-x 屏幕適配新解 – 兼容與擴展

本文出自[無間落葉](轉載請保留出處):http://blog.leafsoar.com/archives/2013/05-13-08.htmlhtml

在讀這篇文章以前,先讀前一篇文章 Cocos2d-x 屏幕適配新解 (http://www.ityran.com/archives/4018)是必要的。算法

若是說前一篇文章文章在 LsSize 提出以前的是基礎,LsSize 是應用,那麼對於這篇文章來講,LsSize 是基礎,而這裏是其的綜合應用,我之初衷是其擴展性和兼容性,激發讀者思惟。也許你並無體會出 LsSize 的強大,而實際上,它能作的比你想象的要多的多,這是前話 ~spa

ShoAll 模式的兼容

首先 LsSize 能知足 ShowAll 模式的須要,由於開始就是把 LsSize 看成 ShowAll 中的 WinSize 來設計的。 而且能夠爲背景作裝飾,而在遊戲設計之時並無什麼區別,LsSize 能夠設定顯示區域的大小,使背景層與 LsSize 分離(這一點在上一篇文章最後已經提到),從而保證了遊戲的元素不會超出 LsSize 而露出到 VisibleSize 的區域內。設計

NoBorder 模式兼容

爲何說 NoBorder 兼容模式,它自己不就是 NoBorder 麼,它與實際的 NoBorder 區別又在何處,有何優點?首先說說兼容,使用此模式,並不影響 你繼續使用 VisibleSize 和 VisibleOrigin(之後簡寫 Visible),你能夠不使用 LsSize 的參考點,而使用 Visible 的相關值獲取屏幕的拐點,遊戲元素按照 Visible 來設置也可。下面詳細介紹基於 LsSize 的 NoBorder 和原油 NoBorder 的區別以及其優點。code

咱們設想這樣一個 實際狀況 。咱們須要一套資源圖片,作爲在適合分辨率的資源展現,當屏幕的大小分辨率在 854×480,800×480,728×480 (橫屏下:爲何高度一樣是 480 而寬度有這麼多值 : P 這也是屏幕適配萬惡之一了吧) 時,咱們使用一套資源,當高度小於 480 時,咱們使用另外一套小的資源是合理的設計。而這裏咱們的資源寬姑且先不論,高必定是 480 最爲合適了,最接近此分辨率的圖片。那咱們使用 NoBorder 的時候該 設置 WinSize 爲多少 了呢?htm

基於 854×480 設計!好,那麼當程序跑在 854×480 的屏幕上,正好滿屏顯示,而圖片資源並無放大或者縮小,或者說基於像素點點對點顯示的。可是當這樣設計的 WinSize 跑在 800×480 和 728×480 分辨率會如何?也許已經知道了,爲了保證小於 854 那一小塊區域的顯示,畫面將會縮小那麼一點點,也許在現在屏幕的 ppi 日益漸高的狀況下,並不十分明顯,但畫面必定是有那麼一點模糊了。同理能夠碰見,不論 WinSize 如何設置,在 三種少量不一樣分辨率下,顯示的效果確定略有不一樣。而分辨率差異越大,這種效果就越明顯。blog

注:細心的朋友已經讀出上文描述中出現的 Bug ,並多謝指出問題的朋友。下面修復 Bug 並從新描述問題的狀況 ~遊戲

折衷方案,咱們基於 800×480 設計,那麼此時出現的狀況是,當跑在 800×480 的屏幕上時,正好滿屏顯示,而圖片並無任何放大或者縮小,或者說基於像素點點對點顯示的。而當這樣設計的 WinSize 跑在 728×480 和 854×480 的分辨率會如何? 854×480 相比 800×480,前者的寬高比要大於後者,因此它是寬對齊的,這意味着,畫面有所放大,而上下將會有一部分殘缺,此時設計高度將會失去參考價值。728×480 相比 800×480 ,前者的寬高比小於後者,因此它是高對齊的,此時畫面並無縮放,只是橫向截取了小部分,這樣的狀況是因爲 NoBorder 的實現機制所決定。固然咱們能夠將設計的寬度設置的很寬很寬,以保證高對齊,哈~可是魔(設計寬度)高一尺,道(實際寬度)高一丈,倒不如使用後文提到的「固定高度」方式了~ 而這裏的 854×480,800×480,728×480 等數據只是屏幕適配等問題的「縮影」圖片

讀到這裏也許已經發現了,LsSize 已經完美(這裏的完美,並不是只此特殊狀況下的解決方法,而是總覽全文,基於 LsSize 的設計理念,其兼容性和可擴展性,顯然在此時,固定高度是更好的實現方式)的解決了這個問題,動態 WinSize ,一個合理的設計,我夢將 LsSize 設定爲 720×480,而且使用 高度爲 480 的圖片資源,而寬度能夠往大了設計,好比 854×480 的圖片資源,讀過前文 LsSize 的實現原理,咱們能夠知道,在這三種狀況下,屏幕的畫面並無縮放,由於實際的寬度老是大於 720 ,從而達不到縮放的條件。480 高度的圖片,可以正好填充 480 高度的屏幕,而圖片的寬度往大了設計,在寬度稍微小的屏幕下,會被截取一部分,但就顯示效果來講,並無什麼損失,而遊戲的元素位置能夠用原來的方法基於 Visible 來設計。資源

爲何能夠作到如此!本來的 NoBorder 經過固定 WinSize 根據屏幕寬高比縮放,因此會有不一樣程度的縮放,而 LsSizeNoBorder 的設計實現,經過屏幕寬高比來得到 WinSize 的值,以保證 LsSize 總能在屏幕上正好所有顯示。

LsSizeNoBorder 比 NoBorder 好,好多少,這就仁者見仁,智者見智了 ~

kResolutionFixedHeight,kResolutionFixedWidth 擴展兼容模式

FixedHeight 和 FixedWidth 是什麼模式,若是你試用了最新版的 cocos2d-x (2.1.3)就能發現這兩種模式,一種是固定設計時的高,一種是固定設計時的寬。而在當前的 2.0.4 並無這兩種模式,而如今,你能夠經過 LsSize 來實現這兩種模式。存在既是合理,FixedHeight 和 FixedWidth 的存在是合理的,好比咱們寫一個橫版過關遊戲,一樣是三種分辨率 854×480,800×480,728×480 使用固定設計高度的方法,能夠避免在 NoBorder 中會根據寬度而作的縮放。

而在 LsSizeNoBorder 中好似也實現了相同的功能!但注意有一點區別,在 LsSizeNoBorder 中,實際屏幕高度爲 480 ,若是寬度小於 720 時,那麼畫面會縮放,而這裏新模式固定高度不會。若是咱們想讓 LsSize 實現這種功能怎麼作,咱們將對 LsSize 的設計稍做擴展,上篇文章的代碼:

CCSize frameSize =CCEGLView::sharedOpenGLView()->getFrameSize();
// 設置 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 須要除以一個放大係數,放大係數能夠由樅方向獲取,
// 由於此時 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);
 
// 根據 LsSize 和屏幕寬高比動態設定 WinSize
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(lsSize.width * scale,
lsSize.height * scale, kResolutionNoBorder);

咱們的實際縮放係數,是根據 scaleX 和 scaleY 的大小來判斷,依據哪一個方向縮放,從而在顯示效果上是高對齊仍是寬對齊。而想要固定是高度對其仍是寬度對其,那隻要換用以下方法便可:

// 要實現這種功能,咱們須要作的就是算得 縮放係數,縮放係數由 原來的設計稍做演變便可
// 因爲 NoBorder 的縮放是根據 scaleX 和 scaleY 的熟大熟小來判斷縮放係數是參照橫向仍是豎向
// 固咱們須要兩個先決條件,固定的方向 和 縮放的參照方向,而獲得以下算法
 
// 固定高度
if(scaleX > scaleY)
scale = scaleX /(frameSize.height /(float) lsSize.height);
else
scale = scaleX /(frameSize.width /(float) lsSize.width);
 
// 固定寬度
if(scaleX > scaleY)
scale = scaleY /(frameSize.height /(float) lsSize.height);
else
scale = scaleY /(frameSize.width /(float) lsSize.width);
  1.  

下面經過幾張效果圖展現 固定高度 和 固定寬度 效果:

顯示效果:(NoBorder 固定高度模式 ;FrameSize = 520×320; LsSize = 480×320; WinSize = 動態獲取)

 圖片

顯示效果:(NoBorder 固定高度模式 ;FrameSize = 520×360; LsSize = 480×320; WinSize = 動態獲取)

 圖片

顯示效果:(NoBorder 固定寬度模式 ;FrameSize = 480×360; LsSize = 480×320; WinSize = 動態獲取)

 圖片

顯示效果:(NoBorder 固定寬度模式 ;FrameSize = 480×300; LsSize = 480×320; WinSize = 動態獲取)

 圖片

如圖所示,咱們固定了一個方向,使得這個方向上的設計長度正好填充屏幕,而另外一個方向上會有所延伸或截取,而此時若是想或者屏幕拐點,能夠配合 Visible 的顯示區域算得。而這也正式 cocos2d-x 2.1.3 所實現的功能,而若是你此時爲了穩定而使用 2.0.4 stable 版本,那麼就能夠經過這種基於 LsSize 的設計方法實現 FixedHeight 與 FixedWidth。 而在未來後續版本穩定,也能夠很平滑的升級到使用自帶的方式替換,其顯示效果同樣,只是後續版本 cocos2d-x 在內部將它封裝了而已。

kResolutionLeafsoar 模式的核心思想

透過現象看本質!基於固定 LsSize 的動態 WinSize 設計。之因此可以兼容這麼多模式而且有所增強,在於 LsSize 在 FrameSize、WinSize、VisibleSize、VisibleOrigin等概念以外的存在,而且經過動態計算 scale 而遊走於此等之間。它的存在並不依賴於 這些已有概念,而反過來,讓已有的概念去依賴 LsSize 。從而保持設計上的靈活性與擴展性。

相關文章
相關標籤/搜索