cocos2d-x多分辨率自适配及因此导致的CCListView的bug修复
cocos2d-x是一款眾所周知的跨平臺(tái)的游戲開發(fā)引擎。由于其跨平臺(tái)的特性,多分辨率支持也自然就有其需求。
因此,在某一次更新中(抱歉,筆者已經(jīng)忘了是哪次更新了),cocos2d-x添加了一個(gè)新的方法,可以非常簡便地讓cocos2d根據(jù)屏幕尺寸的大小做自適配。
方法名:
1 virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);該方法所傳的參數(shù)中,前兩個(gè)參數(shù)width、height,指的是開發(fā)者在設(shè)計(jì)界面時(shí)默認(rèn)設(shè)計(jì)的尺寸。例如:開發(fā)者在設(shè)計(jì)界面時(shí)以iphone5為準(zhǔn),則width和height就是568*320;若是以iphone4為準(zhǔn),則width和height就是480*320;以此類推。
第三個(gè)參數(shù)resolutionPolicy指的是cocos2d在縮放時(shí)需要遵守的規(guī)則。ResolutionPolicy這個(gè)自定義結(jié)構(gòu)如下:
1 enum ResolutionPolicy 2 { 3 // The entire application is visible in the specified area without trying to preserve the original aspect ratio. 4 // Distortion can occur, and the application may appear stretched or compressed. 5 kResolutionExactFit, 6 // The entire application fills the specified area, without distortion but possibly with some cropping, 7 // while maintaining the original aspect ratio of the application. 8 kResolutionNoBorder, 9 // The entire application is visible in the specified area without distortion while maintaining the original 10 // aspect ratio of the application. Borders can appear on two sides of the application. 11 kResolutionShowAll, 12 13 kResolutionUnKnown, 14 };通過注釋可以看出:
kResolutionExactFit是指cocos2d縮放的時(shí)候不考慮畫面失真,直接用畫面填充滿整個(gè)屏幕
kResolutionNoBorder是指cocos2d縮放的時(shí)候盡量頂滿畫面,如果因此有超出畫面的部分,就會(huì)把超出的部分切除掉(舉例來說:如果設(shè)計(jì)大小是568*320,在480*320大小的屏幕上自適配的時(shí)候,就會(huì)把寬度超出的部分切除)
kResolutionShowAll是指cocos2d縮放的時(shí)候顯示所有的畫面,如果有填不滿屏幕的地方就會(huì)顯示黑條。
這三種規(guī)則各有優(yōu)缺點(diǎn),具體使用哪種規(guī)則需要考量項(xiàng)目的需要進(jìn)行合理的選擇。
?
然而,需要特別注意的一點(diǎn)是:setDesignResolutionSize和enableRetina這兩個(gè)方法是不可以同時(shí)使用的。這即意味著使用自適配的時(shí)候是不可以做高清版的。
如果查看cocos2d-x源代碼,可以看到在setDesignResolutionSize方法中有一句代碼:
1 CCAssert(m_bIsRetinaEnabled == false, "can not enable retina while set design resolution size!");在下認(rèn)為這是因?yàn)楦咔迥J较聢D片資源都是進(jìn)行了縮小的,所有的坐標(biāo)都是定義的point,而不是pixel。因此高清模式和自適配可能有某些沖突存在。(以上只是筆者的猜測,不靠譜勿怪)
?
總之,如果想要使用自適配,就必須在項(xiàng)目一開始就放棄高清。如果要做高清版,目前看來就只能自己根據(jù)屏幕尺寸的比例變化設(shè)置setContentScaleFactor,這一部分的設(shè)置方法這里就不展開了。
另外,筆者在剛開始使用自適配功能時(shí),誤以為開發(fā)時(shí)要把UI元素的位置坐標(biāo)和大小都寫成相對(duì)于屏幕大小的一定比例。例如:
1 CCSprite* avatarSprite = CCSprite::create("avatar.png"); 2 avatarSprite->setPosition(ccp(winSize.width * 0.000878, winSize.height * 0.653125)); 3 addChild(avatarSprite);但實(shí)際上這是沒有必要的。自適配功能是直接調(diào)整整個(gè)CCDirector的畫布大小,因此任何添加到CCDirector中的元素都會(huì)被縮放相應(yīng)的比例,沒有必要再特意將坐標(biāo)寫成相對(duì)屏幕比例的模式。
?
下面筆者將分享一下在使用自適配功能的時(shí)候遇到的一個(gè)問題,即CCListView在多分辨率模式下可能出現(xiàn)的被過多地切除一部分內(nèi)容的問題。
首先先介紹下筆者發(fā)現(xiàn)問題時(shí)的背景:當(dāng)時(shí)筆者是在實(shí)現(xiàn)一款跨平臺(tái)的游戲的其中一個(gè)界面,該游戲的畫面是按照iphone5的低清版設(shè)計(jì),DesignResolutionSize設(shè)置的是568*320。在安裝到iphone5上時(shí)一切正常,但是隨后,在安裝到iphone4機(jī)器上進(jìn)行調(diào)試時(shí),發(fā)現(xiàn)畫面上所有的CCListView都被切除了左邊的一部分內(nèi)容。
由于在iphone5上一切正常,在iphone4上畫面被切除了一部分,因此筆者立即懷疑是CCListView與setDesignResolutionSize之間有某些沖突。
通過debug和log,最后將問題鎖定到了CCListView類的visit方法。方法的源代碼如下:
1 void CCListView::visit(void) 2 { 3 if (!m_pListViewParent) 4 { 5 CCRect rectSelf; 6 float factor = CC_CONTENT_SCALE_FACTOR(); 7 rectSelf.origin = convertToWorldSpace(CCPoint(0,0)); 8 rectSelf.origin.x *= factor; 9 rectSelf.origin.y *= factor; 10 rectSelf.size = this->getContentSize(); 11 rectSelf.size.width *= factor; 12 rectSelf.size.height *= factor; 13 glScissor((GLsizei)rectSelf.origin.x, (GLsizei)rectSelf.origin.y, (GLsizei)rectSelf.size.width , (GLsizei)rectSelf.size.height); 14 glEnable(GL_SCISSOR_TEST); 15 } 16 CCLayerColor::visit(); 17 if (!m_pListViewParent) 18 { 19 glDisable(GL_SCISSOR_TEST); 20 } 21 }這段代碼中調(diào)用了一個(gè)方法:glScissor。這個(gè)方法是框定了CCListView將會(huì)顯示在屏幕上的范圍。而由于在使用自適配模式,對(duì)CC_CONTENT_SCALE_FACTOR沒有做任何修改,因此這個(gè)框出來的范圍是對(duì)應(yīng)于DesignResolutionSize設(shè)定的原始設(shè)計(jì)畫面大小的,而在屏幕尺寸發(fā)生了變化,整個(gè)CCDirector被縮放的情況下,這個(gè)rectSelf卻沒有做任何改變,所以就導(dǎo)致了上述的被切除一部分的問題。
隨后,筆者通過搜索,發(fā)現(xiàn)已經(jīng)有人遇到了同一個(gè)問題。而且還提供了修復(fù)的方法:http://www.cocos2d-x.org/boards/18/topics/14464
簡單講就是,用CCEGLView::sharedOpenGLView()->setScissorInPoints方法替換glScissor方法。其它任何地方都不用變。
修改好以后在iphone4和5上調(diào)試都沒問題,因此這個(gè)bug本身可以算是修復(fù)了。
?
PS:由于對(duì)這個(gè)方法能夠奏效感到好奇,筆者查看了setScissorInPoints方法的源文件,代碼如下:
1 void CCEGLViewProtocol::setScissorInPoints(float x , float y , float w , float h) 2 { 3 glScissor((GLint)(x * m_fScaleX + m_obViewPortRect.origin.x), 4 (GLint)(y * m_fScaleY + m_obViewPortRect.origin.y), 5 (GLsizei)(w * m_fScaleX), 6 (GLsizei)(h * m_fScaleY)); 7 }可以看出這個(gè)方法內(nèi)部仍然是調(diào)用了glScissor方法,但是傳遞的參數(shù)則考慮到了屏幕尺寸的變化,因此可以保證通過這個(gè)方法不會(huì)切除過多的CCListView的內(nèi)容。
另外,在工程中搜索glScissor時(shí)發(fā)現(xiàn)CCScrollView也調(diào)用了這個(gè)方法,因此如果使用了CCScrollView推薦也替換掉源代碼中g(shù)lScissor方法。
轉(zhuǎn)載于:https://www.cnblogs.com/atong/archive/2013/05/31/3110938.html
總結(jié)
以上是生活随笔為你收集整理的cocos2d-x多分辨率自适配及因此导致的CCListView的bug修复的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: libxml2编译错误问题
- 下一篇: 树状数组 讲解