首先說點題外話,對於任何大型項目來說,coding的規范重要,在cocos2dx-jsbinding這個框架中,javascript是一個絕對核心的腳本語言,99%的游戲邏輯都由js完成。腳本的編寫量絕對大於大多數的web項目,掌握javascript的扎實的基礎至關重要,這里推薦一篇好的博客,由淺入深的講解從js的一些編寫習慣,到設計模式,值得細細品讀。湯姆大叔的博客:http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html。
進入正題,今天討論的是如何使用jsb來處理移動平台的多分辨率適配問題。就目前的移動平台來講,分辨率可謂是百花齊放,且不談安卓平台各種稀奇古怪的分辨率,就ios平台有ip4(960*640),ip5(1136*640),ipad2,mini(1024*768),ipad3,ipad4(2048*1536),這四種當然今后還有更多,如何保證一套代碼,一套資源通吃android和ios平台,同時游戲的布局又不會發生偏差,能夠恰當好處,這是我們追求的目標。cocos2d-x本身提供有幾種屏幕適配API,但是並不是非常完美,並且每種方案都有自己的缺陷,我介紹一下如何用js來處理這個棘手的問題。首先我們要定義實際使用資源的分辨率,也就是美術設計是用的分辨率大小,這里我們將資源定義為960*640,這個分辨率有什么好處?第一是這個分辨率是一個中等類型的分辨率,它比1年前的主流android分辨率800*480)要大,比新出的高端機型分辨率要小一點,同時也是主流的ios分辨率。選資源大小有一個要點,不能選的過高,這樣對低端機型就是浪費,你需要花很大的下載來存這些資源,不值得,但是選太小的也不行,高端機型上又模糊無比,所以選擇一個中等的分辨率。
分辨率適配的核心思想是縮放,也就是layer.scale函數,但是一定要是等比縮放,如果用layer.scaleX或者layer.scaleY函數,雖然可以把游戲畫面非常簡單的搞成分辨率適配成沒有黑邊,但是整個游戲畫面已經被拉伸或者壓擠,不能達到我們需要的效果。
游戲中一般有3大類層。
1.大於屏幕的層,可實現拖動、縮放或者可以隨着角色移動移動場景畫面的,一般這種場景為主城、副本等等。
2.居中的層,一般是同時基於水平方向和豎直方向居中的,也有基於一個方向居中的。這種一般為ui彈層。
3.靠邊的層,一般是ui,這些ui分別是緊貼屏幕邊緣。
以上幾種類型是基本的類型,當然某一個場景可能是上面幾種層類型的組合。比如一個傳統九宮格的戰報場景,人物的排列是基於居中的,ui分布是靠邊的,實現的時候我們將人物和ui分別繪制再2個layer中,每個layer基於相應的類型進行縮放,就可以達到想要的效果。
下面分別來說明下,三種類型的layer如何做縮放。
第一種:這種其實最簡單,因為這種層的底圖超過屏幕(一般都超出很多,因為要做移動和多點縮放,或者要隨着角色移動至少一屏),所以只要做一個通用縮放就可以,何謂通用縮放,還是看代碼
// 獲取屏幕尺寸 var size = cc.Director.getInstance().getWinSize(); this.designResolution = cc.size(960,640); // 獲取高寬系數 var widthRatio = size.width/this.designResolution.width,heightRatio = size.height/this.designResolution.height; if (widthRatio !=1 || heightRatio!=1){ // 按照比例小的系數去進行縮放 if (widthRatio<heightRatio){ this._scaleRatio = widthRatio; }else{ this._scaleRatio = heightRatio; } }else{ this._scaleRatio = 1; } this.setScale(this._scaleRatio);
第二種:在上面通用縮放的基礎上設定層的坐標,使之可以上下左右居中
var size = cc.Director.getInstance().getWinSize(); this.setPosition(cc.p((size.width-this.designResolution.width*this._scaleRatio)/2,(size.height-this.designResolution.height*this._scaleRatio)/2));
第三種:這種layer是緊靠屏幕邊緣的,所以我們要分別設定他的錨點,我們將整個layer分為9個點,剛好呈現一個“米”字型,其中每個點都需要new一個單獨layer來設定它的錨點。
this._uiLayerMap = this._uiLayerMap || {}; if (this._uiLayerMap[directionType]){ return this._uiLayerMap[directionType]; } var layer = cc.Layer.create(); layer.setPosition(cc.p(0,0)); this._uiLayerMap[directionType] = layer; // 根據directionType設定錨點位置 switch (directionType){ case 1: layer.setAnchorPoint(cc.p(0,1)); break; case 2: layer.setAnchorPoint(cc.p(0.5,1)); break; case 3: layer.setAnchorPoint(cc.p(1,1)); break; case 4: layer.setAnchorPoint(cc.p(1,0.5)); break; case 5: layer.setAnchorPoint(cc.p(1,0)); break; case 6: layer.setAnchorPoint(cc.p(0.5,0)); break; case 7: layer.setAnchorPoint(cc.p(0,0)); break; case 8: layer.setAnchorPoint(cc.p(0,0.5)); break; } this.addChild(layer);
當然,這些層生成完以后還需要做一個通用縮放。使用的時候要注意2點。
1.設定坐標的時候要按照size.width和size.height來計算大小,例如我設定屏幕右下角ui的坐標為
sprite1.setPositon(size.width,50); sprite2.setPositon(size.width-80,50); sprite3.setPositon(size.width-160,50);
2.針對每個角的layer需要選擇上面設定相應錨點layer。