天天看點

Cocos2d适應螢幕分辨率

我使用的版本是cocos2d-2.0-x-2.0.4,cocos2dx-2.0版本對多分辨率适配提供了很好的支援,使用起來比1.0版本要簡單些,1.0版本的适配可以參考這篇博文。

1. 做2.0版本的适配首先需要了解下面這些知識。

(1)适配政策

2.0版本提供了三種适配政策:

kResolutionNoBorder:超出螢幕的部分會被裁剪,兩側沒有黑邊,鋪滿螢幕,按圖檔原始比例顯示,圖檔不變形。

kResolutionShowAll:整個遊戲界面是可見的,會按原始比例進行縮放,圖檔不變形,但兩側可能會留有黑邊,不鋪滿螢幕。

kResolutionExactFit:整個遊戲界面是可見的,圖檔可能會進行拉伸或者壓縮處理,鋪滿螢幕,圖檔會變形。

可以根據自己的要求選擇。

(2)VisibleSize和VisibleOrigin

getVisibleSize:表示獲得視口(可視區域)的大小,如果DesignResolutionSize跟螢幕尺寸一樣大,則getVisibleSize等于getWinSize。

getVisibleOrigin:表示可視區域的起點坐标,這在處理相對位置的時候非常有用,確定節點在不同分辨率下的位置一緻。

(3)DesignResolutionSize

DesignResolutionSize是一個比較重要的概念,其實2.0版本的适配跟1.0版本原理差不多,都是按比例進行縮放。這個DesignResolutionSize表示設計方案,就是你的遊戲完美支援的分辨率方案,一般根據圖檔資源的尺寸來定,自适配時會按照這個分辨率計算出縮放因子。是以,這個值也應該是動态的,如果是橫屏遊戲則高度肯定是鋪滿螢幕的,寬度也要盡可能的鋪滿螢幕,是以應該選擇寬高比最大的作為設計分辨率,下面的demo會給出使用方法。

(4)設定相對位置

在遊戲中使用相對位置設定坐标的好處是顯而易見的,這樣就不需要為每個分辨率都定義一套坐标了。首先得定義一些參考點,引擎的TestCpp例子中就提供了一種方法,以螢幕上可視區域的9個點作為參考點,相當于在該矩形内寫一個米字,這9個點分别是:左上、左、左下、下、右下、右、右上、上、中心。

2. 下面來實作一個簡單的demo,首先建立一個win32工程,這個就不詳述了。

(1)建立一個AppMacros.h檔案,定義了一些宏,源碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#ifndef __APPMACROS_H__

#define __APPMACROS_H__

#include "cocos2d.h"

typedef

struct

tagResource

{

cocos2d::CCSize size;

char

directory[100];

}Resource;

//可用的資源尺寸

static

Resource smallResource  =  { cocos2d::CCSizeMake(480, 320),  

"iphone"

};

static

Resource mediumResource =  { cocos2d::CCSizeMake(1024, 768), 

"ipad"

};

static

Resource largeResource  =  { cocos2d::CCSizeMake(2048, 1536),

"ipadhd"

};

//設計方案

static

cocos2d::CCSize smallDesignResolutionSize = cocos2d::CCSizeMake(480.0f, 320.0f);

static

cocos2d::CCSize mediumDesignResolutionSize = cocos2d::CCSizeMake(1024.0f, 768.0f);

static

cocos2d::CCSize largeDesignResolutionSize = cocos2d::CCSizeMake(2048.0f, 1536.0f);

//縮放因子,主要給文字标簽使用

#define SCALE_FACTOR  (cocos2d::CCEGLView::sharedOpenGLView()->getDesignResolutionSize().width / smallResource.size.width)

#endif

(2)接下來修改AppDelegate.cpp檔案的applicationDidFinishLaunching函數,添加以下代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

bool

AppDelegate::applicationDidFinishLaunching()

{

// initialize director

CCDirector *pDirector = CCDirector::sharedDirector();

CCEGLView *pEGLView = CCEGLView::sharedOpenGLView();

pDirector->setOpenGLView(pEGLView);

CCSize frameSize = pEGLView->getFrameSize();

float

ratio = frameSize.width / frameSize.height;

float

ratio1 = largeDesignResolutionSize.width / largeDesignResolutionSize.height;

float

ratio2 = mediumDesignResolutionSize.width / mediumDesignResolutionSize.height;

float

ratio3 = smallDesignResolutionSize.width / smallDesignResolutionSize.height;

float

d1 =

abs

(ratio - ratio1);

float

d2 =

abs

(ratio - ratio2);

float

d3 =

abs

(ratio - ratio3);

std::map<

float

, CCSize> designSize;

designSize[d1] = largeDesignResolutionSize;

designSize[d2] = mediumDesignResolutionSize;

designSize[d3] = smallDesignResolutionSize;

std::map<

float

, CCSize>::reverse_iterator iter = designSize.rbegin();

//得到key最大的,是以我這裡是橫屏,是以以高度為基準,為了確定縮放後寬度能全屏,是以選取寬高比最大的為設計方案

CCSize designResolutionSize = iter->second;

//pEGLView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionNoBorder);

pEGLView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionShowAll);

//pEGLView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionExactFit);

if

(frameSize.height > mediumResource.size.height)

{

CCFileUtils::sharedFileUtils()->setResourceDirectory(largeResource.directory);

pDirector->setContentScaleFactor(largeResource.size.height/designResolutionSize.height);

}

else

if

(frameSize.height > smallResource.size.height)

{

CCFileUtils::sharedFileUtils()->setResourceDirectory(mediumResource.directory);

pDirector->setContentScaleFactor(mediumResource.size.height/designResolutionSize.height);

}

else

{

CCFileUtils::sharedFileUtils()->setResourceDirectory(smallResource.directory);

pDirector->setContentScaleFactor(smallResource.size.height/designResolutionSize.height);

}

pDirector->setDisplayStats(

true

);

pDirector->setAnimationInterval(1.0 / 60);

CCScene *pScene = HelloWorld::scene();

pDirector->runWithScene(pScene);

return

true

;

}

(3)建立VisibleRect.h和VisibleRect.cpp檔案,封裝了擷取那9個點坐标的函數,比較簡單。代碼如下:

VisibleRect.h

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

#ifndef __VISIBLERECT_H__

#define __VISIBLERECT_H__

#include "cocos2d.h"

USING_NS_CC;

class

VisibleRect

{

public

:

static

CCRect getVisibleRect();

static

CCPoint left();

static

CCPoint right();

static

CCPoint top();

static

CCPoint bottom();

static

CCPoint center();

static

CCPoint leftTop();

static

CCPoint rightTop();

static

CCPoint leftBottom();

static

CCPoint rightBottom();

private

:

static

void

lazyInit();

static

CCRect s_visibleRect;

};

#endif

VisibleRect.cpp

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

#include "VisibleRect.h"

CCRect VisibleRect::s_visibleRect;

void

VisibleRect::lazyInit()

{

if

(s_visibleRect.size.width == 0.0f && s_visibleRect.size.height == 0.0f)

{

CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();

s_visibleRect.origin = pEGLView->getVisibleOrigin();

s_visibleRect.size = pEGLView->getVisibleSize();

}

}

CCRect VisibleRect::getVisibleRect()

{

lazyInit();

return

CCRectMake(s_visibleRect.origin.x, s_visibleRect.origin.y, s_visibleRect.size.width, s_visibleRect.size.height);

}

CCPoint VisibleRect::left()

{

lazyInit();

return

ccp(s_visibleRect.origin.x, s_visibleRect.origin.y + s_visibleRect.size.height/2);

}

CCPoint VisibleRect::right()

{

lazyInit();

return

ccp(s_visibleRect.origin.x+s_visibleRect.size.width, s_visibleRect.origin.y + s_visibleRect.size.height/2);

}

CCPoint VisibleRect::top()

{

lazyInit();

return

ccp(s_visibleRect.origin.x + s_visibleRect.size.width/2, s_visibleRect.origin.y + s_visibleRect.size.height);

}

CCPoint VisibleRect::bottom()

{

lazyInit();

return

ccp(s_visibleRect.origin.x + s_visibleRect.size.width/2, s_visibleRect.origin.y);

}

CCPoint VisibleRect::center()

{

lazyInit();

return

ccp(s_visibleRect.origin.x + s_visibleRect.size.width/2, s_visibleRect.origin.y + s_visibleRect.size.height/2);

}

CCPoint VisibleRect::leftTop()

{

lazyInit();

return

ccp(s_visibleRect.origin.x, s_visibleRect.origin.y + s_visibleRect.size.height);

}

CCPoint VisibleRect::rightTop()

{

lazyInit();

return

ccp(s_visibleRect.origin.x + s_visibleRect.size.width, s_visibleRect.origin.y + s_visibleRect.size.height);

}

CCPoint VisibleRect::leftBottom()

{

lazyInit();

return

s_visibleRect.origin;

}

CCPoint VisibleRect::rightBottom()

{

lazyInit();

return

ccp(s_visibleRect.origin.x + s_visibleRect.size.width, s_visibleRect.origin.y);

}

(4)修改HelloWorldScene.cpp的init函數,使用相對位置設定坐标。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

bool

HelloWorld::init()

{

if

( !CCLayer::init() )

{

return

false

;

}

CCMenuItemImage *pCloseItem = CCMenuItemImage::create(

"CloseNormal.png"

,

"CloseSelected.png"

,

this

,

menu_selector(HelloWorld::menuCloseCallback));

pCloseItem->setPosition(ccpAdd(VisibleRect::rightBottom(),

ccp(-pCloseItem->getContentSize().width/2, pCloseItem->getContentSize().height/2)));

CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);

pMenu->setPosition(CCPointZero);

this

->addChild(pMenu, 1);

CCLabelTTF* pLabel = CCLabelTTF::create(

"Hello World"

,

"Arial"

, SCALE_FACTOR * 24);

pLabel->setPosition(ccpAdd(VisibleRect::top(),

ccp(0, -pLabel->getContentSize().height)));

this

->addChild(pLabel, 1);

CCSprite* pSprite = CCSprite::create(

"HelloWorld.png"

);

pSprite->setPosition(VisibleRect::center());

this

->addChild(pSprite, 0);

CCSprite *pLogoSprite = CCSprite::create(

"icon.png"

);

pLogoSprite->setAnchorPoint( ccp(0, 0.5) );

pLogoSprite->setPosition(ccpAdd(VisibleRect::left(), ccp(50, 0)));

this

->addChild(pLogoSprite, 0);

return

true

;

}

(5)建立視窗,main.cpp的主要内容:

1 2 3 4 5 6 7 8 9 10 11 12

AppDelegate app;

CCEGLView* eglView = CCEGLView::sharedOpenGLView();

//eglView->setFrameSize(2048, 1536);

//eglView->setFrameSize(480, 320);

//eglView->setFrameSize(800, 480);

//eglView->setFrameSize(1024, 768);

//eglView->setFrameSize(1280, 800);

eglView->setFrameSize(1280, 768);

//eglView->setFrameSize(960, 640);

eglView->setFrameZoomFactor(0.5f);

int

ret = CCApplication::sharedApplication()->run();

OK,到此為止,代碼部分已經完成了,下面看看在各種分辨率和不同政策下的效果圖:

1. kResolutionShowAll政策:

(1)2048×1536

Cocos2d适應螢幕分辨率

(2)1024×768

Cocos2d适應螢幕分辨率

(3)480×320

Cocos2d适應螢幕分辨率

(4)800×480

Cocos2d适應螢幕分辨率

(5)1280×800

Cocos2d适應螢幕分辨率

(6)960×640

Cocos2d适應螢幕分辨率

2. kResolutionExactFit政策

1280×768分辨率

Cocos2d适應螢幕分辨率

3. kResolutionNoBorder政策

1280×768分辨率

Cocos2d适應螢幕分辨率

繼續閱讀