1. 程式人生 > >Android遊戲Graphics繪圖之影象畫素操作

Android遊戲Graphics繪圖之影象畫素操作

 

我們在玩遊戲時經常會看到一些影象的特效,比如半透明等效果。要實現這些效果並不難,只需要對影象本身的畫素執行操作。Android中的 Bitmap同樣提供了操作畫素的方法,可以通過getPixels方法來獲得該影象的畫素並放到一個數組中,我們處理這個畫素陣列就可以了,最後通過 setPixels設定這個畫素陣列到Bitmap中。

在Android中,每一個影象畫素通過一個4位元組整數來展現:最高位位元組用作Alpha通道,即用來實現透明與不透明控制,255代表完全不透明,0則代表完全透明;接下來的一個位元組是Red紅色通道,255代表完全是紅色。依次類推,接下來的兩個位元組相應地實現綠色和藍色通道。

下面的示例通過對影象畫素的操作來模擬水紋效果,如圖5-11所示。

實現程式碼如下所示:

001 package com.yarin.android.Examples_05_10;
002
003 import android.content.Context;
004 import android.graphics.Bitmap;
005 import android.graphics.BitmapFactory;
006 import android.graphics.Canvas;
007 import android.view.KeyEvent;
008 import
android.view.MotionEvent;
009 import android.view.View;
010
011 public class GameView extends View implements Runnable
012 {
013 int BACKWIDTH;
014
015 int BACKHEIGHT;
016
017 short[] buf2;
018
019 short[] buf1;
020
021 int[] Bitmap2;
022
023 int[] Bitmap1;
024
025
public GameView(Context context)
026 {
027 super(context);
028
029 /** 裝載圖片 */
030 Bitmap      image = BitmapFactory.decodeResource(this.getResources(),R.drawable.qq);
031 BACKWIDTH = image.getWidth();
032 BACKHEIGHT = image.getHeight();
033
034 buf2 = new short[BACKWIDTH * BACKHEIGHT];
035 buf1 = new short[BACKWIDTH * BACKHEIGHT];
036 Bitmap2 = new int[BACKWIDTH * BACKHEIGHT];
037 Bitmap1 = new int[BACKWIDTH * BACKHEIGHT];
038
039 /** 載入圖片的畫素到陣列中 */
040 image.getPixels(Bitmap1, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT);
041
042 new Thread(this).start();
043 }
044
045
046 void DropStone(int x,// x座標
047 int y,// y座標
048 int stonesize,// 波源半徑
049 int stoneweight)// 波源能量
050 {
051 for (int posx = x - stonesize; posx < x + stonesize; posx++)
052 for (int posy = y - stonesize; posy < y + stonesize; posy++)
053 if ((posx - x) * (posx - x) + (posy - y) * (posy - y) < stonesize * stonesize)
054 buf1[BACKWIDTH * posy + posx] = (short) -stoneweight;
055 }
056
057
058 void RippleSpread()
059 {
060 for (int i = BACKWIDTH; i < BACKWIDTH * BACKHEIGHT - BACKWIDTH; i++)
061 {
062 // 波能擴散
063 buf2[i] = (short) (((buf1[i - 1] + buf1[i + 1] + buf1[i - BACKWIDTH] + buf1[i + BACKWIDTH]) >> 1) - buf2[i]);
064 // 波能衰減
065 buf2[i] -= buf2[i] >> 5;
066 }
067
068 // 交換波能資料緩衝區
069 short[] ptmp = buf1;
070 buf1 = buf2;
071 buf2 = ptmp;
072 }
073
074 /** 渲染你水紋效果 */
075 void render()
076 {
077 int xoff, yoff;
078 int k = BACKWIDTH;
079 for (int i = 1; i < BACKHEIGHT - 1; i++)
080 {
081 for (int j = 0; j < BACKWIDTH; j++)
082 {
083 // 計算偏移量
084 xoff = buf1[k - 1] - buf1[k + 1];
085 yoff = buf1[k - BACKWIDTH] - buf1[k + BACKWIDTH];
086
087 // 判斷座標是否在視窗範圍內
088 if ((i + yoff) < 0)
089 {
090 k++;
091 continue;
092 }
093 if ((i + yoff) > BACKHEIGHT)
094 {
095 k++;
096 continue;
097 }
098 if ((j + xoff) < 0)
099 {
100 k++;
101 continue;
102 }
103 if ((j + xoff) > BACKWIDTH)
104 {
105 k++;
106 continue;
107 }
108
109 // 計算出偏移象素和原始象素的記憶體地址偏移量
110 int pos1, pos2;
111 pos1 = BACKWIDTH * (i + yoff) + (j + xoff);
112 pos2 = BACKWIDTH * i + j;
113 Bitmap2[pos2++] = Bitmap1[pos1++];
114 k++;
115 }
116 }
117 }
118
119 public void onDraw(Canvas canvas)
120 {
121 super.onDraw(canvas);
122
123 /** 繪製經過處理的圖片效果 */
124 canvas.drawBitmap(Bitmap2, 0, BACKWIDTH, 0, 0, BACKWIDTH, BACKHEIGHT, false, null);
125 }
126
127 // 觸筆事件
128 public boolean onTouchEvent(MotionEvent event)
129 {
130
131 return true;
132 }
133
134
135 // 按鍵按下事件
136 public boolean onKeyDown(int keyCode, KeyEvent event)
137 {
138 return true;
139 }
140
141
142 // 按鍵彈起事件
143 public boolean onKeyUp(int keyCode, KeyEvent event)
144 {
145 DropStone(BACKWIDTH/2, BACKHEIGHT/2, 10, 30);
146 return false;
147 }
148
149
150 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
151 {
152 return true;
153 }
154
155 /**
156 * 執行緒處理
157 */
158 public void run()
159 {
160 while (!Thread.currentThread().isInterrupted())
161 {
162 try
163 {
164 Thread.sleep(50);
165 }
166 catch (InterruptedException e)
167 {
168 Thread.currentThread().interrupt();
169 }
170 RippleSpread();
171 render();
172 //使用postInvalidate可以直接線上程中更新介面
173 postInvalidate();
174 }
175 }
176 }
最後,我們就可以用上面的方法實現Android影象畫素操作了,謝謝閱讀!