1. 程式人生 > >cocos2d-x 之 適配解析度全屏的方法

cocos2d-x 之 適配解析度全屏的方法

cocos2d-x 2.0 提供一個極有價值的新特徵: setDesignResolutionSize() 。

這個函式用於指定一個 OpenGL 檢視,然後將這個檢視對映到裝置螢幕上。根據不同的設定,檢視會自動縮放顯示內容,為 cocos2d-x 自適應多種解析度提供了基本支援。

不過要真正實現自適應解析度,從場景設計、美術製作到程式編寫,都需要遵循一套規範,才能極大減少工作量。

注意:本文假定遊戲是橫向顯示的。

~

明確自適應多種解析度的需求

要讓遊戲在不同解析度下都獲得良好的使用者體驗,應該滿足這幾個要求:

  • 背景圖填滿整個畫面,不出現黑邊;
  • 背景圖的主要內容都顯示在螢幕上,儘可能少的裁剪圖片(減少超出螢幕可視區域的部分);
  • 如果背景圖需要放大,儘可能減小放大的比例,避免放大後出現明顯的模糊;
  • 使用者介面的文字標籤、按鈕在任何解析度下都應該完整顯示,並且容易互動。

上述需求實際上可以分解為兩部分:

  • 如何製作滿足多種解析度的背景圖;
  • 如何定位使用者介面元素(標籤、按鈕等)。

~

製作適合多種解析度的背景圖

在開始製作背景圖前,我們看看市面上各種裝置(480 畫素解析度的老裝置 2012 的遊戲應該可以無視了)常見的畫素解析度(resolution in pixels):

Device Width Height
iPad 1024px 768px
New iPad 2048px 1536px
iPhone 960px 640px
Android Phone 1 800px 480px
Android Phone 2 854px 480px
Android Phone 3 1280px 720px
Android Pad 1 1024px 600px
Android Pad 2 1280px 800px

經過幾個遊戲的實踐,我們確定了幾個背景圖的解析度:

  • 2048px * 1536px

    專門針對 New iPad,設計師的原稿也是這個尺寸。

  • 960px * 720px

    這個解析度針對 iPhone 和 iPad 裝置。在 iPhone 上 1:1 顯示,上下各剪裁掉 40px。而在 iPad 上按 1.067 放大顯示,正好填滿整個螢幕,並且使用者看不到模糊。從 2048px 的原稿匯出 PNG 時,按照 0.469 比例縮小正好就是 960px * 720px。

  • 854px * 480px

    市面上的 Android 手機,854px * 480px 和 800px * 480px 是最常見的兩種解析度。2048px 的原稿按照 0.417 比例縮小,然後裁減掉上下多餘部分就可以得到需要的 PNG 圖片。

  • 1280px * 800px

    應付高解析度的 Android 手機和平板裝置,在各種解析度下都可以獲得很好的顯示效果。2048px 的原稿按照 0.625 比例縮小,然後裁減掉上下多餘部分就可以得到需要的 PNG 圖片。

對於美術來說,背景圖都按照 2048px * 1536px 的尺寸繪製。然後用指令碼配合 ImageMagick 就可以自動匯出四種解析度的背景圖片。

如果需要最大程度減小遊戲的下載體積,那麼可以只使用 960px * 720px 的素材。並且參考本文後面示例程式的做法,用一套素材應付各種不同的解析度。

唯一需要注意的問題就是:確保畫面中的主要內容在各種裝置上都位於螢幕的可視區域中

下面幾個圖展示 2048px 原稿在不同裝置上的可視區域:

~

製作適合各種解析度的使用者介面元素

相比背景圖,介面元素的製作只需要考慮一點:必須能夠放置在最小的可視區域中。如下圖介面底部有一排按鈕,這些按鈕在各種解析度下都能完整顯示:

在匯出介面元素的 PNG 圖片時,仍然使用指令碼檔案和 ImageMagick 按照特定比例自動縮放。

~

在各種解析度的螢幕上定位介面元素

準備好了美術素材,接下來的挑戰就是如何在不同解析度的裝置中定位介面元素。

為了解決這個問題,我們做了大量的嘗試,最終找到一種可行的解決方案,而且使用起來非常簡單。

虛擬解析度

為了簡化程式的開發,我們使用一個統一的虛擬座標系來對映裝置的螢幕。經過幾個產品的實踐,證明將螢幕寬度設定為 960pt 是很合理的。

特別注意:在討論虛擬座標系時,一律使用 pt(Point)作為單位,而不是 px(Pixel)。

下面的表格整理了各種裝置解析度與 960pt 寬度虛擬解析度的對應關係:

Device Width Height Virtual Width Virutal Height Scale
iPad 1024px 768px 960pt 720pt 1.066666667
New iPad 2048px 1536px 960pt 720pt 2.133333333
iPhone 960px 640px 960pt 640pt 1.0
Android Phone 1 800px 480px 960pt 576pt 0.833333333
Android Phone 2 854px 480px 960pt 540pt 0.889583333
Android Phone 3 1280px 720px 960pt 540pt 1.333333333
Android Pad 1 1024px 600px 960pt 562pt 1.066666667
Android Pad 2 1280px 800px 960pt 600pt 1.333333333

根據參考點定位介面元素

在遊戲初始化時,引擎就會根據裝置的實際解析度,自動設定好對應的虛擬解析度,並且確定螢幕上的幾個參考點:

Position Value
left 0pt
right 959pt
top 虛擬解析度的高度 - 1
bottom 0pt
center x 480pt
center y 虛擬解析度的高度 / 2

有了參考點,定位介面元素就很簡單了。例如一個按鈕的原點(按鈕圖片中心點)相對於螢幕左側 40pt,相對於螢幕底部 30pt。那麼在不同解析度的裝置上,這個按鈕和螢幕左下角的距離都是差不多的。

只要確保所有介面元素都使用參考點來定位,那麼就絕不會出現在裝置螢幕上看不到介面元素的情況。

~

示例程式

為了方便大家進行測試,本文的示例工程已經編譯成 Windows 可執行檔案。執行時可以用下列命令列啟動以便測試不同解析度:

命令列引數
1
2
# 如果沒有指定命令列引數,則預設使用 960px * 640px 的螢幕解析度。
multires.demo1.win32.exe 854 480

或者雙擊 test_multires.cmd 直接檢視不同解析度的執行效果。

其他:

  • 示例程式只包含按照 960px * 720px 製作的素材。

~

補充說明

本文前面描述瞭如何建立適合不同解析度的圖片,但最後的示例程式並沒有考慮這一點,而是用一套素材就搞定了多種解析度。實際上,我個人推薦使用一套素材適應多種解析度,最多再為 New iPad 單獨準備一套素材,這樣可以顯著減少工作量。

如果一定要按照不同解析度使用不同的素材,那麼在顯示圖片時需要呼叫 setScale() 調整圖片的縮放比例。這樣做的原因是 setDesignResolutionSize() 設定虛擬解析度後,會指定一個全域性的縮放比例,所有的圖片即便是 scale = 100%,也會自動縮放。所以當圖片尺寸和虛擬解析度不一致時,我們就需要手動調整圖片縮放比例了。

假設裝置解析度是 1280px * 720px,虛擬解析度是 960pt * 540pt,背景圖是 1280px * 800px。要確保背景圖 1:1 顯示在螢幕上,參考如下程式碼:

讓圖片按 1:1 顯示在螢幕上
1
2
3
4
5
6
const CCSize& winSize = CCDirector::sharedDirector()->getWinSize();
float scale = CCEGLView::sharedOpenGLView().getScaleX();
CCSprite* bg = CCSprite::create("bg.jpg")
bg->setPosition(ccp(winSize.width / 2, winSize.height / 2));
bg->setScale(1.0f / scale); // 這裡重置圖片縮放比例,確保圖片按 1:1 顯示在螢幕上
addChild(bg);

~

-EOF-