Cocos2d-x 3.1 一步步做屏幕適配

本文並不想講關於屏幕適配的概念或者大道理,如果還不瞭解cocos2d-x屏幕適配的,請先看這篇文檔:《Cocos2d-x 多分辨率適配完全解析》。本文有一些內容和圖片是引用這篇文章的。看了那麼多網上關於屏幕適配的文章,還是覺得似懂非懂,所以最好的方法就是自己一步步做好適配。


一、根據屏幕尺寸選擇“最”合適的圖片

如果根據屏幕尺寸來選擇一樣大小的圖片,那麼美工要哭了,因爲對於安卓機,各種各樣的分辨率啊,不僅美工要哭了,程序員也要哭了。所以,我們只能選擇最合適的圖片,比如320*500分辨率和300*480分辨率的屏幕可以使用320*480的圖片。


1、在Cocos2d-x自帶的解決方案中就有針對iphone、ipad和ipadhd所做的適配方案,在工程cpp-empty-test有例子

// AppMacros.h
#define DESIGN_RESOLUTION_480X320    0
#define DESIGN_RESOLUTION_1024X768   1
#define DESIGN_RESOLUTION_2048X1536  2

// 要切換設計方案,改變這一行即可
#define TARGET_DESIGN_RESOLUTION_SIZE  DESIGN_RESOLUTION_480X320

typedef struct tagResource
{
    cocos2d::Size size;		// 尺寸
    char directory[100];	// 資源路徑
}Resource;

static Resource smallResource  =  { cocos2d::Size(480, 320),   "iphone" };
static Resource mediumResource =  { cocos2d::Size(1024, 768),  "ipad"   };
static Resource largeResource  =  { cocos2d::Size(2048, 1536), "ipadhd" };

#if (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_480X320)
static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_1024X768)
static cocos2d::Size designResolutionSize = cocos2d::Size(1024, 768);
#elif (TARGET_DESIGN_RESOLUTION_SIZE == DESIGN_RESOLUTION_2048X1536)
static cocos2d::Size designResolutionSize = cocos2d::Size(2048, 1536);
#else
#error unknown target design resolution!
#endif

// 480*320的字體大小是24號,根據當前的分辨率來修改字體大小
#define TITLE_FONT_SIZE  (cocos2d::Director::getInstance()->getOpenGLView()->getDesignResolutionSize().width / smallResource.size.width * 24)

從上面可以看出,Cocos2d-x定義了三種大小,分別是iphone(480*320),ipad(1024*768),ipadhd(2048*1536),一般用得比較多的是iphone和ipad。


我們再看一下資源文件夾,工程->Resource下:

1408601401936634.png

iphone目錄:

1408601442812874.png

ipad目錄:

1408601457292556.png

ipadhd目錄:

1408601484602166.png

也就是說,在這三個文件夾裏面有三套不同大小分辨率的圖片,我們之後根據屏幕大小來選擇對應的圖片就行了。


2、實現怎麼根據屏幕大小來選擇圖片

新建一個工程,再將AppMacros.h文件拷貝過去。

// AppDelegate.cpp
bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
        glview = GLView::create("My Game");
		glview->setFrameSize(480, 320);	// 在這裏設置創建窗口的尺寸,手機上這個就不用啦,因爲手機有固定的屏幕
        director->setOpenGLView(glview);
    }

	auto screenSize = glview->getFrameSize();	// 獲取屏幕尺寸
	std::vector<std::string> searchPaths;

	// 這裏是實現的重點,比較屏幕的高和設定的三種適配尺寸的高,選擇合適的圖片
	// 然後將對應圖片的路徑添加到搜索路徑中,那麼cocos2d-x就會到該目錄去尋找圖片
	if (screenSize.height > middleResource.size.height)
	{
		searchPaths.push_back(largeResource.directory);
	}else if (screenSize.height > smallResource.size.height)
	{
		searchPaths.push_back(middleResource.directory);
	}else
	{
		searchPaths.push_back(smallResource.directory);
	}
	
	FileUtils::getInstance()->setSearchPaths(searchPaths);

    // turn on display FPS
    director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0 / 60);

    // create a scene. it's an autorelease object
    auto scene = HelloWorld::createScene();

    // run
    director->runWithScene(scene);

    return true;
}


3、改變窗口尺寸來看效果

窗口尺寸500*300:

1408601551811748.png

因爲高300小於320,所以使用480*320的圖片。這時候看到的是左右有黑邊,上下被截了一點。沒事,下面會講怎麼解決。


窗口尺寸700*300:

1408601570475146.png

還是用480*320分辨率的,都是300的錯。


窗口尺寸800*480:

1408601589253283.png

這次用的是1024*768的了,因爲320<480<768。


在500*300尺寸中我們看到圖片左右因爲不夠寬而出現黑邊,而上下因爲太大了而被截取了一部分,那麼要怎麼解決這個問題呢?往下看。


二、圖片與屏幕“完美”融合

爲了使圖片能與屏幕“完美”融合,Cocos2d-x提供了一組相關的接口和5種分辨率適配的策略。


首先了解一下三種分辨率:

  • 資源分辨率:也就是圖片分辨率,下面寬Resource Width簡寫爲RW,高Resource Height簡寫爲RH。

  • 設計分辨率:也就是我們設定區域的分辨率,下面寬Design Width簡寫爲DW,高Design Height簡寫爲DH。

  • 屏幕分辨率:也就是窗口分辨率,下面寬Screen Width簡寫爲SW,高Screen Height簡寫爲SH。


Cocos2d-x的圖片顯示有下面兩個過程:

  • 從資源分辨率到設計分辨率;

  • 從設計分辨率到屏幕分辨率;

1408601647526990.png

這個過程就是:

1、先選定目標的設計分辨率,在AppMacros.h中我們定義了三種分辨率,分別是480*320,1024*768,2048*1536:

1408601675715621.png

默認選中的是480*320:

1408601697252652.png

2、從資源分辨率到設計分辨率

通過setContentScaleFactor()函數來縮放圖片的分辨率,以適應設計分辨率的大小。這個函數的參數不是通過資源寬/屏幕寬、資源高/屏幕高得來的,而是通過資源寬/設計分辨率寬、資源高/設計分辨率高得來的。這樣我們就可以不關注屏幕尺寸,先根據現有的資源跟選好的設計分辨率來做好適配。


在上面800*480尺寸的圖中可以看到,圖片四邊都被截取了,原因就是沒有做好圖片的縮放,接下來我們先用setContentScaleFactor()來做圖片縮放。


設計分辨率選擇的是480*320,窗口分辨率480*321,這樣用的就是1024*768分辨率的圖片了:

	if (screenSize.height > middleResource.size.height)
	{
		searchPaths.push_back(largeResource.directory);
		director->setContentScaleFactor(largeResource.size.height/designResolutionSize.height);
	}else if (screenSize.height > smallResource.size.height)
	{
		searchPaths.push_back(middleResource.directory);
		// 縮放因子是資源寬/設計分辨率寬
		director->setContentScaleFactor(middleResource.size.height/designResolutionSize.height);	
	}else
	{
		searchPaths.push_back(smallResource.directory);
		director->setContentScaleFactor(smallResource.size.height/designResolutionSize.height);
	}

效果:

1408601775196573.png

用高度比作爲內容縮放因子,保證了背景資源的垂直方向在設計分辨率範圍內的全部顯示。


修改縮放因子爲資源寬/設計寬:

// 縮放因子是資源寬/設計分辨率寬
director->setContentScaleFactor(middleResource.size.width/designResolutionSize.width);

用寬度比作爲內容縮放因子,保證了背景資源的水平方向在設計分辨率範圍內的全部顯示。


可以參考一下這張圖,我的是橫屏的,這張圖畫的是豎屏的,不過原理一樣:

1408601816870942.png

3、從設計分辨率到屏幕分辨率

設計分辨率是我們自定義分辨率方案,圖片根據設計分辨率做好了縮放效果了,如果跟屏幕分辨率適配,說白了就是一廂情願。最後一步就是使用setDesignResolutionSize()函數來實現設計分辨率到屏幕分辨率的完美適配了:

void GLViewProtocol::setDesignResolutionSize(float width,	// DW
float height,	// DH
ResolutionPolicy resolutionPolicy)	// 適配策略


五種適配策略:

enum class ResolutionPolicy  
{  
    EXACT_FIT,  
    NO_BORDER,  
    SHOW_ALL,  
    FIXED_HEIGHT,  
    FIXED_WIDTH,  
  
    UNKNOWN,  
};

先看不使用適配策略的情況,在第2中,設置窗口分辨率爲960*640:

1408601871779840.png

接着,我們使用setDesignResolutionSize()函數來適配設計分辨率和屏幕分辨率:

glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::EXACT_FIT);

效果:

1408601908833743.png

這時候就是我們想要的效果了。


上面說到共有五種分辨率適配的策略,其實就是從設計分辨率適配到屏幕分辨率時,圖片拉伸的策略:

1、ResolutionPolicy::SHOW_ALL

屏幕寬、高分別和設計分辨率寬、高計算縮放因子,取較(小)者作爲寬、高的縮放因子。保證了設計區域全部顯示到屏幕上,但可能會有黑邊。


2、ResolutionPolicy::EXACT_FIT

屏幕寬

與設計寬比作爲X方向的縮放因子,屏幕高與設計高比作爲Y方向的縮放因子。保證了設計區域完全鋪滿屏幕,但是可能會出現圖像拉伸。


3、ResolutionPolicy::NO_BORDER

屏幕寬、高分別和設計分辨率寬、高計算縮放因子,取較(大)者作爲寬、高的縮放因子。保證了設計區域總能一個方向上鋪滿屏幕,而另一個方向一般會超出屏幕區域。


如圖:

1408601976914785.png

ResolutionPolicy::NO_BORDER是之前官方推薦使用的方案,他沒有拉伸圖像,同時在一個方向上撐滿了屏幕,但是新加入的兩種策略將撼動ResolutionPolicy::NO_BORDER的地位。

ResolutionPolicy::FIXED_HEIGHT和ResolutionPolicy::FIXED_WIDTH都是會在內部修正傳入設計分辨率,以保證屏幕分辨率到設計分辨率無拉伸鋪滿屏幕。


4、ResolutionPolicy::FIXED_HEIGHT

保持傳入的設計分辨率高度不變,根據屏幕分辨率修正設計分辨率的寬度。

適合高方向需要撐滿,寬方向可裁減的遊戲,結合setContentScaleFactor(RH/DH)使用。


5、ResolutionPolicy::FIXED_WIDTH

保持傳入的設計分辨率寬度不變,根據屏幕分辨率修正設計分辨率的高度。

適合寬方向需要撐滿,高方向可裁減的遊戲,結合setContentScaleFactor(RW/DW)使用。


如圖:

20140810114202742.png

屏幕適配的就講到這裏了,網上講屏幕適配這方面的文章也很多,但都是理論知識,個人覺得最好的學習方法就是去做個demo,一步步做,看看效果如何,這樣才能掌握。

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