調色板貼圖與位圖貼圖的特點描述(J2ME的Image和SymBian的CFbsBimap)
Graphics.drawImage();
J2ME的貼圖函數drawImage()以及SymBian c++的貼圖函數GC.Bitblt()函數貼圖的好處:(以下只說J2ME)
1. 簡單,貼圖函數算法全部內部實現,只需要進行函數參數調用。
2. J2ME平台可以使用game包(雖然我從來不用:)
但是,這種簡單的貼圖函數卻有不少的缺點
1. 底層被封裝,使得開發人員不能對底層數據進行操作.(比如alpha混合,灰度,對象換色)
2. 占用內存大,以現在的主流彩色手機為例子,一般的彩屏手機為4096色、65000色甚至24萬色,4096色格式的444位模式,65000色為565的格式,那麼,每一個象素必須占用16為,即2個byte,更不用說24萬色模式了。
3. 貼圖速度慢,對於單個位圖的繪畫,J2ME平台上的繪畫速度是和貼圖的次數相關,這樣就限制了游戲畫面的細膩度,所以經常可以看見很多游戲使用32X32的塊圖。
調色板貼圖描述:
缺點
1. 實現復雜, 前期開發時間長。必須自己實現圖片的繪畫,包括總共8個方向的翻轉。(做的我吐血,但是好處多多)
2. 速度的不確定,比如,在nokia平台,以前的老40CPU比較慢,自己實現的象素貼圖就非常慢,明顯不如系統的貼圖函數,但在6600,7610等60平台就基本持平了。
好處就多了:
1. 支持象素級的訪問,alpha混合,人物變色,角色透明等都很簡單了,而不需要象png圖片一樣非要存一個alpha通道,並且永遠不能變.
2. 占用內存小,因為一個象素只占用一個byte,所以一般用調色板做一張圖片大體只需要原來位圖占用內存的一半。
3. 速度快,這個快有點不絕對,相對的來說,如果游戲使用的圖層越多,那麼用Graphics.drawImage()肯定就會非常慢。在此我對比我做的一個游戲,在nokia 7610平台,采用8層背景圖層,加上大約10個角色貼圖,不采用任何的優化算法,耗時100-120ms之間。
4. 可以完全杜絕J2ME的內存出錯這個bug。當然,自己必須實現游戲的內存管理。
另外:可能會有人疑問,png圖片是經過壓縮的,但自己做的調色板完全不用png,那打包的jar文件不就很大麼?完全沒問題,因為png圖片與jar文件的壓縮算法都是zip的lz77壓縮算法,所以當你的txt文件存儲進jar中時會進行壓縮,壓縮比基本上與png一樣。
下面說一下我的調色板游戲實現方法:
在J2ME平台上,可以用midp2.0的Graphics.drawRGB將象素繪畫到屏幕上(midp1.0中就只能使用廠商的api了,比如nokia的dg.drawPixels()),一般這個只需要調用一次,也就是將象素貼到屏幕上。
游戲中使用兩種圖片: (為了容易理解,我用類進行封裝)
1. 對應Graphics.drawRGB的屏幕位圖:
class RGBImage{
public int imageWidth;
public int imageHeight;
public int[] imageData;//長度 = imageWidth* imageHeight;
};
2. 對應調色板的圖片集合
class PalletteImages {
public int[128] palette;
public int imageNumbers;
public int[] imageSize;
public int[] imageDataFromIndex;
public byte[] data;
};
為什麼要調色板為128呢?因為Java中的byte為-127 - +127,要用256色就必須算加法,如果不想用,就只能用0-127,所以就定義為128的長。根據我的使用經歷,128色完全夠用。
ImageSize存儲每一張圖片的大小,例如:總共有20張圖,那麼imageSize的長度就起碼為20*2 = 40。第n張圖的尺寸寬度=imageSize[n*2],高度 = imageSize[n*2+1]。
ImageDataFromIndex存儲每一張圖片在data數據中的開始位置。
data存儲圖片的索引數據,存儲為如下格式:
圖片1索引1,圖片1索引2,………. 圖片1索引n,
圖片2索引1,圖片2索引2,………. 圖片2索引m,
.
.
.
圖片d索引1,圖片d索引2,………. 圖片d索引g
另外,如果游戲中可以不使用線程(比如nokia的手機就可以不用),也盡量不要用。因為Java虛擬機中本身也有個時鐘周期(此時鐘周期非CPU的時鐘周期,只是我隨便叫個名字而已),並且比線程的時鐘周期精確度高。
比如在nokia平台
用Thread:
int threadDelay;//幀時間
public class GameCanvas extends FullCanvas implements Runnable{
public void run(){
//游戲處理
…………………….
try{
Thread.sleep(threadDelay);
}catch(Exception e){}
}
};
一般只能運行大約10fps(6600,7610等SymBian 7.0平台,N70等8.0平台可能會快些)。
如果這樣做:
long nextTime, currentTime;
int threadDelay;//幀時間
Boolean isThreadRun = true;
public void loopRun(){
nextTime = System.currentTimeMillis();
while(isThreadRun){
currentTime = System.currentTimeMillis();
if(currentTime>=nextTime){
//游戲處理
………………..
timeProcess = System.currentTimeMillis() - currentTime;
if(timeProcess>=threadDelay){
nextTime = currentTime+timeProcess+1;
}else nextTime = currentTime+threadDelay;
}
}
}
那麼可以運行到13fps(6600,7610等SymBian 7.0平台),速度提升非常客觀。
在C/ C++上實現如下:
typedef unsigned char U8;//8位無符號整數
typedef unsigned short int U16;//16位無符號整數
typedef unsigned long int U32;//32位無符號整數
struct Size{
int iWidth;
int iHeight;
};
屏幕位圖:
struct RGBImage{
Size iImageSize;
U32* iImageData;
}
調色板圖片集合:
struct PalletteImages{
U32* iPallette;//256色的調色板,C/C++支持使用256色調色板
int iImageItemNumbers;//圖片總數
Size* iImageSize;//每張圖片尺寸
int* iImageFromIndex;//每張圖片的開始索引
U8* iImageData;//圖片索引數據
};