调色板贴图与位图贴图的特点描述(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平台),速度提升非常客观。