【讀書筆記《Android游戲編程之從零開始》】14.游戲開發基礎(Bitmap 位圖的渲染與操作)


Bitmap 是圖形類,Android 系統支持的圖片格式有 png、jpg、bmp 等。

對位圖操作在游戲中是很重要的知識點,比如游戲中需要兩張除了大小之外其他完全相同的圖,那么如果會對位圖進行縮放操作,很容易就節約了一張圖片資源;這樣既節約了美工的時間,更節約游戲安裝包的大小;當然除了縮放,還有很多操作,例如對位圖進行旋轉、鏡像、設置透明度等等操作都會節約很大的資源。

首先創建一個位圖實例。位圖的實例不能通過 new,如果想通過一張圖片資源文件創建一個位圖,則要通過位圖工廠來索引圖片資源文件,從而生成一張位圖實例,如下所示:

BitmapFactory.decodeResource(Resources res,int Id)

作用:通過資源文件生成一張位圖

第一個參數:資源實例

第二個參數:資源ID

 

懂得如何通過圖片資源創建位圖實例后,下面就來詳細介紹如何操作位圖。創建項目“BitmapProject”,游戲框架為 SurfaceView 游戲框架。具體步驟參照“11.游戲開發基礎(SurfaceView 游戲框架、View 和 SurfaceView 的區別)”。

我這個准備了一張圖片pic01.png:

修改 MySurfaceView.java ,代碼中 bmp 是由圖片資源生成一個位圖實例。

Bitmap bmp = BitmapFactory.decodeResource(this.getResources(),R.drawable.pic01);

 

下面講解位圖常用的操作函數:

1.繪制位圖

                /**
                 * 在畫布上繪制一張位圖
                 * 第一個參數:位圖實例
                 * 第二、三個參數:位圖的X,Y坐標
                 * 第四個參數:畫筆實例
                 */
                canvas.drawBitmap(bmp,0,0,paint);

代碼執行效果如下:

 

2.旋轉位圖

                /**
                 * 旋轉畫布
                 * 第一個參數:畫布旋轉的角度
                 * 第二、三個參數:畫布的旋轉點
                 * 如果旋轉的角度大於0,順時針旋轉;旋轉的角度小於0,則逆時針旋轉
                 *
                 * Canvas 中旋轉畫布還有一個函數:rotate(float degress),參數傳入的是旋轉畫布的角度,此種方法無法設置旋轉點,默認旋轉點為屏幕中心點。
                 */
                canvas.rotate(30,bmp.getWidth()/2,bmp.getHeight()/2);
                canvas.drawBitmap(bmp,0,0,paint);

代碼執行效果如下:

如果想讓位圖進行旋轉,那么通過這種旋轉畫布的方法即可實現。但是當使用此種實現畫布旋轉時,需要注意兩點:

• 如果希望圖片的旋轉是以圖片中心點進行旋轉,那么在使用 rotate 旋轉畫布函數對畫布進行旋轉時,其旋轉點坐標應該設置為圖片的中心點坐標;

• rotate 函數是對整個畫布進行旋轉操作,也就是意味着,畫布上所有繪制的元素都會因畫布的旋轉而進行對應的旋轉。

例如代碼修改為:

                canvas.rotate(30,bmp.getWidth()/2,bmp.getHeight()/2);
                canvas.drawBitmap(bmp,0,0,paint);
                canvas.drawBitmap(bmp,100,0,paint);

當旋轉畫布后,繪制兩個位圖,效果圖如下所示:

通過圖片可以明顯看出,第二次繪制的圖片也被旋轉!當然這並不是想要的效果,那么如果只想對一張位圖進行旋轉操作該如何實現呢?

Canvas 類中有兩個很重要的函數 save() 與 restore():

• save():作用是用於保存當前畫布的狀態;

• restore():作用是恢復上次保存的畫布狀態。

這兩個函數是配對出現的。 注意 save() 函數出現的次數不能大於 restore() 函數。

 

對位圖旋轉代碼進行修改:

                //先保持畫布的狀態
                canvas.save();
                canvas.rotate(30,bmp.getWidth()/2,bmp.getHeight()/2);
                canvas.drawBitmap(bmp,0,0,paint);
                //再將畫布恢復狀態
                canvas.restore();
                canvas.drawBitmap(bmp,100,0,paint);

項目運行效果如下:

所以,當對畫布進行縮放、旋轉和位移操作時,為了保證其他繪制的元素不受影響,應該利用 save() 與 restore() 對畫布進行適當的保持與恢復操作。

 

除此之外 還有一種對位圖進行旋轉的方式,就是利用矩陣 Matrix 來實現,代碼如下:

                //首先創建一個矩陣實例
                Matrix mx = new Matrix();
                //然后對矩陣進行旋轉縮放
                mx.postRotate(30,bmp.getWidth()/2,bmp.getHeight()/2);
                //最后使用畫布繪制位圖時,將矩陣信息作為參數傳入
                canvas.drawBitmap(bmp,mx,paint);

效果如下:

Matrix 類的 postRotate 函數與 Canvas 中的 rotate 函數的作用相同,參數表示的函數也都一致。

使用矩陣對位圖進行操作時,可以免去對畫布的狀態保持和恢復,因為矩陣就是針對單獨位圖進行的操作,所以不會影響畫布其他元素的繪制。

 

3.平移位圖

                //創建位圖實例
                Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.pic01);
                
                canvas.save();
                /**
                 * 平移圖片
                 * 第一個參數:在X軸上平移畫布的距離
                 * 第二個參數:在Y軸上平移畫布的距離
                 */
                canvas.translate(100, 0);
                canvas.drawBitmap(bmp, 0, 0, paint);
                canvas.restore();
                
                canvas.save();
                canvas.translate(-90, 280);
                canvas.drawBitmap(bmp, 0, 0, paint);
                canvas.restore();
                
                canvas.save();
                //利用矩陣也可以完成對位圖的平移操作
                Matrix maT = new Matrix();
                maT.postTranslate(380,-90);
                canvas.drawBitmap(bmp, maT, paint);
                canvas.restore();

代碼執行效果如下:

 

4.縮放位圖

                //創建位圖實例
                Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.pic01);
                
                canvas.save();        
                canvas.drawText("原圖:", 0, 20, paint);    
                canvas.drawBitmap(bmp, 0, 40, paint);
                canvas.restore();

                canvas.save();
                /**
                 * 對畫布進行縮放
                 * 第一個參數:對畫布X軸的縮放比例
                 * 第二個參數:對畫布Y軸的縮放比例
                 * 此方法無法設置縮放起始點,默認縮放起始點為屏幕的(0,0)點
                 */
                //縮小到0.5倍
                canvas.scale(0.5f, 0.5f);
                canvas.drawBitmap(bmp, 600, 40, paint);
                canvas.restore();
                
                canvas.save();
                /**
                 * 對畫布進行縮放
                 * 第一個參數:對畫布X軸的縮放比例
                 * 第二個參數:對畫布Y軸的縮放比例
                 * 第三、四個參數:對畫布進行縮放的起始點
                 */
                //放大為2倍
                canvas.scale(2f, 2f, 0, 0);
                canvas.drawBitmap(bmp, 0, 220, paint);
                canvas.restore();
                
                canvas.save();
                //,利用矩陣實現對位圖的縮放操作,當前為縮小到0.75倍
                Matrix ma = new Matrix();
                ma.postTranslate(700, 40);
                ma.postScale(0.75f, 0.75f);
                canvas.drawBitmap(bmp,ma, paint);
                canvas.restore();

代碼執行效果如下:

 

5.鏡像反轉位圖

                //創建位圖實例
                Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.pic01);
                
                canvas.save();        
                canvas.drawText("原圖:", 10, 20, paint);    
                canvas.drawBitmap(bmp, 10, 40, paint);
                canvas.restore();                
                
                //X 軸鏡像
                canvas.save();
                canvas.drawText("X 軸鏡像:", 10, 320, paint); 
                //當X軸的比例值小於0時,其實是對畫布進行X軸的鏡像后的縮放。
                canvas.scale(-1, 1, 10+bmp.getWidth()/2, 340+bmp.getHeight()/2);
                canvas.drawBitmap(bmp, 10, 340,paint);
                canvas.restore();
                
                //Y 軸鏡像
                canvas.save();
                canvas.drawText("Y 軸鏡像:", 10, 620, paint); 
                //利用矩陣實現對位圖的鏡像操作
                Matrix ma = new Matrix();
                ma.postTranslate(10, 640);
                ma.postScale(1, -1, bmp.getWidth()/2+10,bmp.getHeight()/2+640);
                canvas.drawBitmap(bmp,ma, paint);
                canvas.restore();
                
                //XY 軸鏡像
                canvas.save();
                canvas.drawText("XY軸鏡像:", 10, 920, paint); 
                canvas.scale(-1, -1, 10+bmp.getWidth()/2, 940+bmp.getHeight()/2);
                canvas.drawBitmap(bmp, 10, 940,paint);
                canvas.restore();

代碼執行效果如下:

 

在游戲開發中,一般最經常用的是 png 格式的圖片,原因在於 png 格式的圖片支持透明度,當然這不是必須的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM