這個東西很煩人,相信很多人都不理解
今天來總結一下,首先有很多概念都要事先弄得清楚明白
1.屏幕分辨率
所謂屏幕分辨率相信很多人都知道他的概念,不就是1280pxX720PX嗎?不就是這種形式嗎?有什么難的,這幾個詞在各種手機評測上面不是已經用爛了嗎?
可是很多人都沒有真正理解這個概念!!!
1280pxX720px
它的意思是縱向1280個像素,橫向720個像素。
記住!只是像素而已,和尺寸,和大小,和比例沒有半毛錢的直接關系
我一直都以為為什么這個東西要叫做屏幕分辨率,為什么要叫做分辨率?之前一直覺得名不符實,一直以為像素不過是另一種度量單位,深受我們攝影老師的影響,誤人子弟,現在想起來,真是naive!
記住,像素不是一種新的,類似cm,mm的單位,像素並不是一種計量長度的單位,至於他究竟是什么,對不起,無可奉告,自己看百度百科
可以知道的是:像素越密,清晰度越高
2.屏幕分辨率和屏幕尺寸
先說說屏幕尺寸,這東西,才是我們直觀感受到的東西,什么屏幕的大小啊,屏幕的尺寸啊,屏幕的比例啊,一切的一切都落在這個屏幕尺寸上,
接下來就是干貨了
1.相同比例和大小的尺寸,屏幕上的像素分辨率越高,屏幕,越清晰!!!(這個足可以證明尺寸,大小和分辨率無關吧)
2.同樣的屏幕分辨率(比如1280pxX720px),用在不同的屏幕上,我們看到的效果天差地別!!!
接下來進入正題!在游戲中是怎么做的!!
接觸過各種引擎或者直接做游戲的人應該都知道,在游戲中我們做游戲都是以像素作為單位的,比如,一張精靈的圖片,100pxX30px,怎樣處理呢?
在windows平台是這樣的,因為windows平台是窗口式程序,一個游戲程序可以設置它的窗口大小,也就是說,他的屏幕尺寸並不是固定的!!
這個時候是分為兩部分處理的:
1.設置窗口的大小:長寬;這一步相當於人為地規定了屏幕的尺寸(以像素的形式)
2.設置設計尺寸:根據各種手段,使精靈圖片適配窗口的大小
而在移動端,包括安卓端和蘋果端:因為並不是窗口式的OS,事實上就那么點屏幕,也做不了窗口式的OS,所以屏幕並不可更改所以只有一個步驟:
設置設計尺寸:根據各種手段,使屏幕適配窗口的大小
好,解決方案就是以上兩種思想,我來仔細解釋一下,我們知道,因為各種電腦,各種手機,尺寸都不一樣,分辨率也他媽不一樣,這對於開發者來說是一個很復雜的問題,你想想,不同的尺寸,市面上真是數不勝數,我們怎么辦呢?
好,開發者決定以像素為單位,進行開發,這個方法不錯,畢竟各種圖片,紋理,都是以像素為單位的
,可是相同的像素大小,也就是相同的分辨率,在不同平台上的尺寸都不一樣,比如說,同樣是960pxX720px,在這個手機上也許尺寸更大一些,那個手機上,也許尺寸更小一些?我們怎么緊緊跟隨尺寸呢?畢竟,尺寸和分辨率是兩回事啊!!
這個任務實際上是交給手機廠商的!!怎么樣?是不是有一種很爽的感覺!!,這就是產業鏈啊!!!以前總在知乎上看他們辯論產業鏈優勢,現在終於體會到了,對於廠商來說,分辨率就是寫上去的事兒,很簡單,可是解決了我們一個大麻煩,這樣,對於我們來說,從手機設備廠商上獲得的分辨率,就是尺寸啊!!!! 他在邏輯上並不是尺寸,但是這並不妨礙我們把他當作尺寸來看待!!!!
好了,有了以上的解釋,
對於PC端:第一步設置窗口大小的時候,實際上可以認為我們是在認為設置安卓手機的大小尺寸,怎么樣,是不是有一種很吊的感覺!!!模仿手機端,我們是以像素來代替尺寸
第二步的處理接下來在手機端一起講
對於安卓端:
第一步對於安卓端來說不用考慮。
第二步:獲得固定的尺寸分辨率(自己發明的:即可以代表尺寸的分辨率):這一步對於開發者來說是透明的,也就是說,開發者這一步並不知道 具體的分辨率是多少,系統會自動給與
記作ScreenX和ScreenY
開發者自定義一個尺寸,我們稱之為設計尺寸,仍然以像素為單位,記作designX和designY
scaleX=ScreenX/designX
scaleY=ScreenY/designY
然后就選擇適配方式:
有鋪滿屏幕:那就用scaleXxdesignX,scaleYXdesignY來獲得實際的尺寸,注意在這個過程中,場景中的精靈等等都這樣變換,也就是說,游戲場景可能會變形得比較厲害
有保持比例而且不超出屏幕:也就是保持比例不變形且不對素材進行裁剪:實現的時候是對選擇scaleX和scaleY中較小的一個作為縮放因子,對designX和designY進行縮放
有保持比例而且不留空白:也就是保持比例不變形,且充分利用屏幕的每個空間:實現的時候是對選擇scaleX和scaleY中較大的一個作為縮放因子,對designX和designY進行縮放
有保持比例且按照寬度鋪滿屏幕:也就是保持比例不變形,且讓寬度剛好鋪滿屏幕,實現的時候用scaleX作為縮放因子,對designX和designY進行縮放
有保持比例且按照高度度鋪滿屏幕:也就是保持比例不變形,且讓寬度剛好鋪滿屏幕,實現的時候用scaleY作為縮放因子,對designX和designY進行縮放
總結一下,后四種其實是一種類似的思想,
終於把理論部分說完了,感覺上面講完了,cocos2d-x里面的也沒有什么講的了,cocos里面的思想和這個就是一樣的,
直接上函數
glview->setDesignResolutionSize(720,1280,ResolutionPolicy::SHOW_ALL);
這個函數其實就是第二步驟的完整函數,這個前一部分指定我們設計游戲的時候用的尺寸分辨率,然后后面的就是適配風格了
怎么實現這種適配風格可以看看源碼
void GLView::setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy) { CCASSERT(resolutionPolicy != ResolutionPolicy::UNKNOWN, "should set resolutionPolicy"); if (width == 0.0f || height == 0.0f) { return; } _designResolutionSize.setSize(width, height); _resolutionPolicy = resolutionPolicy; updateDesignResolutionSize(); }
這個是setDesignResolutionsize函數,可以看到,通過參數指定了私有成員_designResolutionSize的值,這個就是設計分辨率!!但是注意一下,opengl創建窗口的時候(請原諒我用窗口這個詞),並不是以設計尺寸分辨率創建的,
可以看到,這個函數里只是指定了設計尺寸和適配風格,並沒有實現適配風格,可以猜一下,實現應該封裝在updateDesignResoltionSize里了,進去看看
void GLView::updateDesignResolutionSize() { if (_screenSize.width > 0 && _screenSize.height > 0 && _designResolutionSize.width > 0 && _designResolutionSize.height > 0) { _scaleX = (float)_screenSize.width / _designResolutionSize.width; _scaleY = (float)_screenSize.height / _designResolutionSize.height; if (_resolutionPolicy == ResolutionPolicy::NO_BORDER) { _scaleX = _scaleY = MAX(_scaleX, _scaleY); } else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL) { _scaleX = _scaleY = MIN(_scaleX, _scaleY); } else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) { _scaleX = _scaleY; _designResolutionSize.width = ceilf(_screenSize.width/_scaleX); } else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) { _scaleY = _scaleX; _designResolutionSize.height = ceilf(_screenSize.height/_scaleY); } // calculate the rect of viewport float viewPortW = _designResolutionSize.width * _scaleX; float viewPortH = _designResolutionSize.height * _scaleY; _viewPortRect.setRect((_screenSize.width - viewPortW) / 2, (_screenSize.height - viewPortH) / 2, viewPortW, viewPortH); // reset director's member variables to fit visible rect auto director = Director::getInstance(); director->_winSizeInPoints = getDesignResolutionSize(); director->_isStatusLabelUpdated = true; director->setGLDefaultValues(); } }
可以看到,這個里面實現了上面講的那些適配風格的適配方法
看到這里,我們應該大體能猜到,最終創建的窗口應該是那個叫做_viewPortRect的東西,好了,屏幕適配就寫到這里了,今天狀態不好,從今天起,決定戒掉小說,OK!
今天更新一下,主要是最近自己的項目中間出現一個非常麻煩的問題,今天終於解決了,關於觸摸響應位置不准確的問題,其實主要是windows平台上設置產生的窗口大小超過了PC的物理尺寸大小!!!
詳細的解釋見下面的鏈接