Android遊戲開發 遊戲框架的搭建 3

2021-09-07 21:53:23 字數 4473 閱讀 5156

5. 影象模組(graphics)

最後乙個模組是影象操作模組,用來繪製影象到螢幕上。不過要想高效能的繪製影象,就不得不了解一些基本的影象程式設計知識。讓我們從繪製2d影象開始,首先要了解的乙個問題是:影象究竟是如何繪製到螢幕的?答案相當複雜,我們不需要知道所有的細節。

光柵、畫素和幀緩衝(framebuffers)

現在的顯示器都是基於光柵的,光柵是乙個兩維度的格仔組成,也就是畫素格。光柵格仔的長寬,我們一般用畫素來表示。如果仔細觀察顯示器(或者用放大鏡),我們就可以發現顯示器上面有乙個乙個的格仔,這就是畫素格或者光柵格。每個畫素的位置可以用座標表示,於是引入了二維座標系統,這也意味著座標值是整數。顯示器源源不斷地收到從圖形處理器傳過來的影象流,解碼每個畫素的顏色(程式或者作業系統設定),然後繪製到螢幕上。每秒鐘顯示器會進行多次重新整理,重新整理頻率單位是hz,比如lcd顯示器主流重新整理率是85hz。

下圖是顯示器柵格和幀緩衝區的簡單示意圖:

垂直同步和雙緩衝

普通的繪圖方法,當要繪製的物件太複雜,尤其是含有點陣圖時,這時的畫面會顯示的很慢,對於運動的畫面,會給人「卡」住了的感覺,有時候還會導致畫面閃爍。於是我們採用雙緩衝技術(採用兩個framebuffer)。 雙緩衝的原理可以這樣形象的理解:把電腦螢幕看作一塊黑板。首先我們在記憶體環境中建立乙個「虛擬「的黑板,然後在這塊黑板上繪製複雜的圖形,等圖形全部繪製完畢的時候,再一次性的把記憶體中繪製好的圖形「拷貝」到另一塊黑板(螢幕)上。採取這種方法可以提高繪圖速度,極大的改善繪圖效果。下面是原理圖:

要知道什麼是垂直同步,必須要先明白顯示器的工作原理。顯示器上的所有影象都是一線一線的掃瞄上去的,無論是隔行掃瞄還是逐行掃瞄,顯示器,都有2種同步引數——水平同步和垂直同步。水平同步訊號決定了crt畫出一條橫越螢幕線的時間,垂直同步訊號決定了crt從螢幕頂部畫到底部,再返回原始位置的時間,而恰恰是垂直同步代表著crt顯示器的重新整理率水平!

關閉垂直同步:我們平時執行作業系統一般螢幕重新整理率一般都是在85hz上下,此時顯示卡就會每按照85hz的頻率時間來傳送乙個垂直同步訊號,訊號和訊號的時間間隔是85的解析度所寫一屏影象時間。

開啟垂直同步:在遊戲中,或許強勁的顯示卡迅速的繪製完一屏的影象,但是沒有垂直同步訊號的到達,顯示卡無法繪製下一屏,只有等85單位的訊號到達,才可以繪製。這樣fps自然要受到作業系統重新整理率執行值的制約。也就是說,當然開啟後如果你的遊戲畫面fps數能達到或超過你顯示器的重新整理率,這時你的遊戲畫面fps數被限制為你顯示器的重新整理率。如果達不到會出現不同程度的跳幀現象,fps與重新整理率差距越大跳幀越嚴重。一般對於高效能的顯示卡建議打卡,遊戲畫面會更好!開啟後能防止遊戲畫面高速移動時畫面撕裂現象,比如實況足球等。

關閉垂直同步,那麼遊戲中作完一屏畫面,顯示卡和顯示器無需等待垂直同步訊號,就可以開始下一屏影象的繪製,自然可以完全發揮顯示卡的實力。

但是,不要忘記,正是因為垂直同步的存在,才能使得遊戲程序和顯示器重新整理率同步,使得畫面平滑,使得畫面穩定。取消了垂直同步訊號,固然可以換來更快的速度,但是在影象的連續性上,效能勢必打折扣。這也是關閉垂直同步後發現畫面不連續的理論原因!

影象格式

比較流行的兩個圖形格式是jpeg和 png。jpeg是有失真壓縮格式,png是無失真壓縮格式,因此png格式可以百分百重現原始的影象。有失真壓縮格式通常占用少的磁碟空間。我們採用何總壓縮格式取決於我們的磁碟空間。和音訊類似,當我們載入到記憶體中時,我們需要完全地解壓乙個影象。因此,即使你的壓縮影象在磁碟上只有20k,在ram中你依然需要width×height ×color depth的儲存空間。

影象疊加

這個過程就叫做影象的合成和疊加,我們需要把不同的合成乙個最終顯示的。繪製的此項很重要,因為上面的總會覆蓋下面的。

上面影象合成出現了問題:第二張的白色背景覆蓋了第一張背景。我們怎樣把第二張圖的白色背景消去呢?這就需要alpha混合(alpha blending)。alpha混合是一種把源點的顏色值和目標點的顏色值按照一定的演算法進行運算,得到一種透明的效果。

下面是最終合成影象的rgb值,公式如下

red = src.red * src.alpha + dst.red * (1 – src.alpha)

blue = src.green * src.alpha + dst.green * (1 – src.alpha)

green = src.blue * src.alpha + dst.blue * (1 – src.alpha)

src和dst分別是我們需要混合的源影象和目標影象(源影象相當於人物,目標影象相當於背景)。下面是乙個例子。

src = (1, 0.5, 0.5), src.alpha = 0.5, dst = (0, 1, 0)

red = 1 * 0.5 + 0 * (1 – 0.5) = 0.5

blue = 0.5 * 0.5 + 1 * (1 – 0.5) = 0.75

red = 0.5 * 0.5 + 0 * (1 – 0.5) = 0.25

效果如下圖所示

上述公式用了兩次乘法,乘法消耗的時間多,為了提高運算速度,可以進行優化。如

red = (src.red- dst.red) * src.alpha + dst.red

alpha是乙個浮點數,我們可以轉換成整數運算,因為一種顏色最多佔8bit,所以alpha值最多是256,於是我們把alpha的值乘以256,然後運算的時候再除以256,就得到下面的公式:

red = (src.red- dst.red) * src.alpha /256+ dst.red

這裡,alpha是乙個0到256的數值。

具體到這個例子,我們只需要把原始檔的白色畫素的alpha值設為0即可。最終效果如下圖:

影象模組的介面**

通過以上介紹,我們可以開始設計我們的影象模組的介面。問下需要實現如下功能:

這裡用兩個介面來實現:graphics和 pixmap,下面是graphics介面:

package com.badlogic.androidgames.framework;

public

inte***ce graphics

public pixmap newpixmap(string filename, pixmapformat format);

public

void clear(int color);

public

void drawpixel(int x, int y, int color);

public

void drawline(int x, int y, int x2, int y2, int color);

public

void drawrect(int x, int y, int width, int height, int color);

public

void drawpixmap(pixmap pixmap, int x, int y, int srcx, int srcy, int srcwidth, int srcheight);

public

void drawpixmap(pixmap pixmap, int x, int y);

public

int getwidth();

public

int getheight();

}

列舉 pixmapformat儲存了該遊戲支援的畫素的顏色值(包括透明度)。比如argb8888,a表示透明度,r表示紅色,g表示綠色,b表示藍色,他們非別用8位來表示,就是各有256種狀態。接下來看下介面的方法:

接下來我們看一下pixmap介面:

//

pixmap介面

package com.badlogic.androidgames.framework;

import com.badlogic.androidgames.framework.graphics.pixmapformat;

public

inte***ce pixmap

android 遊戲開發框架

activity類 必要屬性 各種su ceview 各種動畫執行緒 各種聲音 mediaplayer或者soundpool handler 根據收到的mssage切換su ceview或者更新控制項 entity類 必要的屬性 記錄位置,寬高等 dodraw cancas cancas 繪製自己 ...

Android 遊戲開發 View框架

按鍵盤的上下鍵矩形就會上下移動 通過例項化handler物件並重寫handkemessage方法實現了乙個訊息接收器。然後再執行緒中通過sendmessage方法傳送更新介面的訊息,接收器收到更新介面的訊息時便執行invalidate方法更新螢幕顯示。package com.yarin.androi...

android遊戲開發

1 容器我們準備自定義viewgroup 叫做game2048layout 裡面的塊塊自定義view 叫做game2048item 接下來從簡單的開始 2 game2048item game2048item是個view,並且需要哪些屬性呢?首先得有個number,顯示數字嘛,然後繪製的時候根據num...