十一月's profileNOVEMBREBlogListsGuestbookMore Tools Help

Blog


    April 15

    古代帝国中的图片资源节省算法

    {geshibot lang="javascript"}/**
      * 图片转换
      * @param content 原始图片信息
      * @param type 类型,1 :中立角色 2 : 敌方 0 :自己
      */
     public static void imgConvert(byte content[], int type){
      try{
       int pos = 33;
       int relpos = 0;
       relpos = ((content[pos] & 0xff) << 24 | (content[pos + 1] & 0xff) << 16 |
       (content[pos + 2] & 0xff) << 8 | content[pos + 3] & 0xff) & -1;
       pos += 4;
       int newcolor = -1;
       for(int idx = 0; idx < 4; idx++)
        newcolor = pixelConvert(content[pos + idx], newcolor);
       pos += 4;
       boolean flag = true;
       boolean flag1 = false;
       boolean flag2 = false;
       for(int idx = pos; idx < pos + relpos; idx += 3){
        int b = content[idx] & 0xff;
        int g = content[idx + 1] & 0xff;
        int r = content[idx + 2] & 0xff;
        if(r > b && r > g){
         //绿色和蓝色互换,中立角色
         if(type == 1){
          int tmp = b;
          b = g;
          r = b;
          g /= 2;
          }
          //转换为红色,敌人角色
         else if (type == 2){
          b = r;
          g = r;
          }
         content[idx] = (byte)b;
         content[idx + 1] = (byte)g;
         content[idx + 2] = (byte)r;
         }
        newcolor = pixelConvert(content[idx], newcolor);
        newcolor = pixelConvert(content[idx + 1], newcolor);
        newcolor = pixelConvert(content[idx + 2], newcolor);
        }
       newcolor = ~newcolor;
       int actpos = 41 + relpos;
       content[actpos] = (byte)(newcolor >> 24);
       content[actpos + 1] = (byte)(newcolor >> 16);
       content[actpos + 2] = (byte)(newcolor >> 8);
       content[actpos + 3] = (byte)newcolor;
       }
      catch(Exception e){}
      }
     /**
      * 像素转换
      * @param pixel 像素
      * @param color 颜色值
      * @return
      */
     public static int pixelConvert(byte pixel, int color){
      int tmp = pixel & 0xff;
      color ^= tmp;
      for(int idx = 0; idx < 8; idx++)
       if((color & 1) != 0)
       //土黄色
        color = color >>> 1 ^ 0xedb88320;
       else
        color >>>= 1;
      return color;
      }{/geshibot}

     

     

    效果图如下
    原始图


    用代码进行转换的效果图


    注意 :为了能让你的程序实现转换更简单,也就是说你怎么知道要变换那些颜色值。例如上面说的转换条件为:
    r > b && r > g

    所以一张图片的设计,像素的取舍需要跟美工配合好,需要画什么样的图片,以及需要转换的像素点。也可见MacroSpace中美工和程序是紧密地结合在一起的,做到了代码实现更方便以及用代码来节省图片资源

     

    J2ME平台PNG图像压缩、解压与加密技术

           在J2ME平台上PNG图片格式几乎成为了标准,无数台手持设备上运行的J2ME程序几乎都选用PNG来显示图像,包括大量的手机游戏以及手机应用,所以对PNG文件格式的了解,可以更有效的减少Jar Size,保护自有知识产权。
            CoCoMo曾经对PNG文件进行过一段时间的研究,包括图像压缩、解压以及加解密等,现将研究心得记录如下:

    PNG文件格式:
            PNG文件格式分为PNG-24和PNG-8,其最大的区别是PNG-24是用24位来保存一个像素值,是真彩色,而PNG-8是用8位索引值来在调色盘中索引一个颜色,因为一个索引值的最大上限为2的8次方既128,故调色盘中颜色数最多为128种,所以该文件格式又被叫做PNG-8 128仿色。
           PNG-24因为其图片容量过大,而且在Nokia和Moto等某些机型上创建图片失败和显示不正确等异常时有发生,有时还会严重拖慢显示速度,故并不常用,CoCoMo认为这些异常和平台底层的图像解压不无关系。不过该格式最大的优点是可以保存Alpha通道,同事也曾有过利用该图片格式实现Alpha 混合的先例,想来随着技术的发展,手机硬件平台的提升,Alpha混合一定会被广泛的应用,到那时该格式的最大优势才会真正发挥。
           PNG-8文件是目前广泛应用的PNG图像格式,其主要有六大块组成:
    1.文件头
    2.IHDR块
    3.PLTE块
    4.tRNS块
    5.IDAT块
    6.文件尾

    这六大块按顺序排列,也就是说IDAT块永远是在PLTE块之后,期间也会有许多其他的区块用来描述信息,例如图像的最后修改时间是多少,图像的创建者是谁等,不过这些区块的信息对我们来说都是可有可无的描述信息,故压缩时一般先向这些区块开刀。

    数据块:
    除了文件头,其中四大数据块和文件尾都是由统一的数据块文件结构描述的:
            Chunk Length: 4byte
            Chunk Type:   4byte
            Chunk Data:   Chunk Length的长度
            Chunk CRC:    4byte
    例如IHDR块的数据长度为13,既
            Chunk Length = 13
            Chunk Type = "IHDR"

    文件头:
    用来标示PNG文件,为固定的64个字节:0x89504e47 0x0d0a1a0a

    IHDR块:
    用来描述图像的基本信息,其格式为:
           图像宽:    4byte
           图像高:    4byte
           图像色深: 4byte
           颜色类型: 1byte
           压缩方法: 1byte
           滤波方法: 1byte
           扫描方法: 1byte
    曾经有人问过我,撒叫滤波方法和扫描方法,汗,说实话我也不知道,不过我们是在做手机游戏,不是在搞图形学不是嘛。

    PLTE块:
    这个就是传说中放置调色盘数据的地方啦,其格式为:
          循环
               RED:    1byte
               GREEN:1byte
               BLUE:  1byte
          END
    循环长度嘛,不就是Chunk Length / 3的长度嘛,而且Chunk Length一定为3的倍数。

    tRNS块:
    这个块时有时无,主要是看你是否使用了透明色。该区块的格式为:
          循环
               if(对应调色盘颜色非透明)
                   0xFF:  1byte
               else
                   0x00:  1byte
          END
    循环长度为调色盘的颜色数,相当于调色盘颜色表的一个对应表,标识该颜色是否透明,0xFF不透明,0x00透明。故如果用UltraEdit查看PNG文件的二进制编码,如果看到一大片FF,一般就是tRNS区块啦,因为一个PNG文件一般只有一个透明色。

    IDAT块:
    这个就是存放图像数据的地方啦,这里要注意的是一个PNG文件可能有多个IDAT区块,而其他三大区块只可能有一个。
    IDAT 区块是经过压缩的,所以数据不可读,压缩算法一般为LZ77滑动窗口算法,如果硬要看里面的数据的话,用zlib库也是可以的,CoCoMo当年就见过 Windows Mobile上的帝国时代巨变态的用zlib库压缩和解压该区块来进一步减少PNG文件大小,真是寸K寸金啊。

    IEND块:
    该区块虽然也按照数据块的结构,但Chunk Data是没有的,所以是固定的96个字节:0x00000000 0x49454e44 0xae426082

    PNG图像压缩:
            了解了PNG的文件结构,压缩就有的放矢了。压缩有6个级别,可以根据需要选择。
    Level1:读取PNG文件,将除六大块之外的所有区块都过滤掉
    Level2:文件头是固定的0x89504e47 0x0d0a1a0a,文件尾是固定的0x00000000 0x49454e44 0xae426082,去掉!
    Level3:每个区块的Chunk Type我们是否需要呢?很明显,我们自己写的压缩格式自己应该清楚是按照什么样的顺序,去掉!
    Level4:每个区块的Chunk Length我们是否需要呢?
               IHDR块:定长13个字节,明显不需要,去掉。
               PLTE块:最多128个颜色,为撒要用4byte来记录区块长度而不是用1byte来记录颜色数呢?
               tRNS块:既然有颜色数,tRNS又是调色盘颜色表的对应表,既数量与颜色数相同,为撒还需要呢?
               IDAT块:我想这个是唯一需要4byte来记录长度的区块。
    Level5:每个区块的Chunk CRC是否需要呢?
               因为计算CRC需要一些时间,但对于字节较少的区块一般可以忽略不计,所以对于这个问题还是由程序员自己决定吧。对于CRC的计算可以参看CoCoMo的另一篇Blog“PNG文件的CRC码计算
    Level6:每个区块我们是否要原封不动的保存期数据呢?
              IHDR块:除了宽、高、色深是需要的,后面那4byte的信息是固定的0x03000000
              PLTE块:为撒要用3byte来表示RGB而不是2byte的565格式?压缩方法可以参看CoCoMo的另一篇Blog“关于PNG图像压缩的一点感悟
              tRNS块:我想tRNS块是冗余最多的区块了吧,大段大段的0xFF明显没有必要,一般的PNG文件只有一个透明色,为撒要用对应表的方法而不是一个索引来记录到底哪个是透明色呢?由于颜色数最多128,所以只需1byte就可以代替tRNS那么多0xFF啦。
              IDAT块:么想法,如果你够变态,把zlib加进来吧!

    PNG图像解压:
            创建了自定义的文件,J2ME端读取后,就面临解压的问题了。我们可以利用此函数来创建Image:
    static Image
    createImage(byte[] imageData, int imageOffset, int imageLength)

         前提是传入的imageData与PNG未被压缩前的一致。因为PNG文件格式是固定的,所以读取自定义的压缩文件后,开始将那些默认的数据再添加进去,实现解压的目的。下面就开始解压之旅吧!
    首先要创建一个ByteArrayOutputStream out,
    1.写入文件头:
    out.writeInt(0x89504e47);
    out.writeInt(0x0d0a1a0a);
    2.写入IHDR块
    out.writeInt(13);
    out.writeInt(0x49484452);  //0x49484452为Chunk Type "IHDR"
    out.writeInt(width);
    out.writeInt(height);
    out.writeByte(depth);
    out.writeInt(0x03000000);  //压缩时舍掉的4byte,默认0x03000000
    out.writeInt(crc);
    其他区块方法一致,故略过。。。
    3.写入文件尾
    out.writeInt(0x00000000);
    out.writeInt(0x49454e44);
    out.writeInt(0xae426082);
    4.转换成数组,创建Image
    byte[] pngBuffer = out.toByteArray();
    Image image = Image.createImage(pngBuffer, 0, pngBuffer.length);
    哈哈,大功告成。这里注意如果中途数据写入有错误,经常会出现创建Image失败的异常,而且非常不好调试,不过只要自定的压缩格式定下来后,对应的创建Image的函数只要写一次,以后基本不会出问题哈。

    PNG图像加解密:
            很多人都担心自己辛苦创作的漂亮的美术图片很easy就被别人拿到了,究其原因是由于PNG文件格式是固定的,稍微了解的人用UltraEdit很容易就能找到IHDR,PLTE等标识了。CoCoMo就经常看GameLoft的图像文件,哈哈。一般是2byte的Length,然后紧接着图片数据,都放在一个文件里,直接拷贝2进制然后粘贴到一个新文件里就是一幅图。后来的加密技术会把PNG分块,例如前100个字节一块,紧接着1K一块,最后剩余字节一块,然后把块顺序打乱,用2byte来记录总长度,1byte记录顺序,但是这并没有从根本上消除IHDR,IEND这些显眼的定位标识,好像在对破解者说:嘿,看,我就在这里!
           现在了解了之前的压缩和解压技术,这个问题也就迎刃而解了,因为Chunk Length,Chunk Type和Chunk CRC这些东西都消失了,甚至连数据块本身的数据都修改了,我可以按照ImageWidth、ImageHeight、ImageDepth的顺序写数据,也可以倒过来写。我想再牛的PNG分析器也是无能为力的吧,唯一可以定位的就只有IDAT区块了,不过就算得到该区块的数据,也应该是一张黑白图。
           不过在加解密的领域真是道高一尺,魔高一丈,CoCoMo很希望和各位共同探讨,共同提高!

    深入J2ME配置层

    Java 2 Micro Edition (J2ME)是建立在一个由profiles,配置,虚拟机和主持操作系统等部分所组成的标准架构之上的。这些内容组成了完整的J2ME实时运行环境。图A显示了这些部分是如何结合在一起的。J2ME提供了两种配置: Connected Limited Device Configuration (CLDC)和 the Connected Device Configuration (CDC)。这两种配置以设备的内存footprint为基础面向不同的设备类型。

    配置指定了最小的功能组和相关的Java 虚拟机 (JVM)应支持的Java类库。从概念上讲,配置层在虚拟机 (VM)的顶端运行,但当你使用一个例如CLDC和CDC的配置时,你也会涉及到相关的VM,因为二者是紧密相连的。

    然而,应该注意的是在J2ME中,配置并不附属于一个特定的VM,他可以与其它的VM工作并支持所需的库。例如,CLDC也可以和应用指定基础功能的VM共同工作。关于细节,请见CLDC HotSpot应用虚拟机白页。

    为了帮助你理解J2ME配置层所扮演的角色,我将对CLDC和CDC分别地进行阐述。

    CLDC
    CLDC 是针对少于512KB内存footprint的设备的配置。CLDC采用的是KVM,它是高度优化的JVM方式,他针对的是16比特或32比特的微处理器,160到512 KB内存为基础的低端,网络连接,电池驱动的设备。典型的内存要求是128KB做有来存储KVM和相关的库。更多关于KVM的信息可以从Sun公司的KVM白页中得到。

    就网络化而言,CLDC针对的是有限的和间歇性的无线连接设备,所有在J2ME CLDC之上运行的应用软件都应能在其他任何高端的Java VM上运行。当然,这需要CLDC库的支持。CLDC配置关注于I/O,网络化,安全问题,国际化问题和核心 Java库等相关的领域。

    与事件处理,用户和应用程序的互动,应用程序生存期管理等内容相关的领域是由Profile来处理的。使用界面定义(对于特定的设备,如传呼机,移动电话和PDA)也在Profile层的范围之内,它建立在顶端之上,并使用J2ME配置。 Mobile Information Device Profile (MIDP)是一个J2ME profile,它定义了使用CLDC配置设备的用户界面相关的规范。

    CLDC从J2SE获得绝大多数的类,但一些针对小内存footprint设备的新类并不是从J2SE APIs获得的。关于类从J2SE 做继承和新CLDC类的具体信息,可参考CLDC规范1.0a版本的6.2和6.3中的内容。Java语言规范中的一些例外是没有浮点支持,没有类实例的完成化支持和有限的错误处理能力。

    在这里提到CLDC HotSpot应用也是具有相关性的,它相当于使用 CLDC配置的设备的KVM中Java VM的替换。根据Sun公司,CLDC HotSpot执行VM是一个高性能的JVM(32位,采用 CLDC v1.0规范)。他在相同的内存footprint上运行时提供比KVM高出一个数量级的更佳的性能。

    CDC:完全Java平台
    CDC是应用在具有较大内存,特别是2MB以上的设备上的,CDC针对有限和间歇的无线连接设备,CDC与CVM和Foundation profile共同定义了完全的J2ME环境。

    CVM是为用户和嵌入设备设计的完全功能性JVM,它支持所有的Java 2 v1.3 VM安全防护,JNI, JVMDI, RMI,弱引用功能和库。本质上说,CVM具有所有一个驻留桌面系统的JVM所具有的功能。

    CDC由J2SE中最小的Java数据包组成。Foundation profile由用户设备所需要的保持类库和APIs所组成。因此,如果你工作在一个以CDC为基础的J2ME环境下,你就需要更新你代码以使APIs更新换代。

    CDC是CLDC的一个扩展集,所以在两种配置之间存在着向上的兼容性。CDC和Foundation profile也提供了对使用PersonalJava实时规范开发的应用程序的完全兼容。

    总结
    J2ME 模式体系使能了不同设备类别的“特别版”Java的创建。随着越来越多的设备制造商开始接受J2ME技术和J2ME设备使用范围的增大,更新的 J2ME profiles将得到应用。通过为开发以Java为基础的设备提供一个公共最小化平台,J2ME配置用结构化的方式使能了这些Java特别版本。

    使用调色板进行手机游戏开发 (转)

    调色板贴图与位图贴图的特点描述(j2meImageSymbianCFbsBimap

     
    Graphics.drawImage();

    J2me的贴图函数drawImage()以及Symbian c++的贴图函数GC.Bitblt()函数贴图的好处:(以下只说j2me)

    1.  简单,贴图函数算法全部内部实现,只需要进行函数参数调用。

    2.  J2me平台可以使用game包(虽然我从来不用:

    但是,这种简单的贴图函数却有不少的缺点

    1.  底层被封装,使得开发人员不能对底层数据进行操作.(比如alpha混合,灰度,对象换色)

    2.  占用内存大,以现在的主流彩色手机为例子,一般的彩屏手机为4096色、65000色甚至24万色,4096色格式的444位模式,65000色为565的格式,那么,每一个象素必须占用16为,即2byte,更不用说24万色模式了。

    3.  贴图速度慢,对于单个位图的绘画,J2ME平台上的绘画速度是和贴图的次数相关,这样就限制了游戏画面的细腻度,所以经常可以看见很多游戏使用32X32的块图。

     

    调色板贴图描述:

    缺点

    1.  实现复杂, 前期开发时间长。必须自己实现图片的绘画,包括总共8个方向的翻转。(做的我吐血,但是好处多多)

    2.  速度的不确定,比如,在nokia平台,以前的老40CPU比较慢,自己实现的象素贴图就非常慢,明显不如系统的贴图函数,但在6600,761060平台就基本持平了。

     

    好处就多了:

    1.  支持象素级的访问,alpha混合,人物变色,角色透明等都很简单了,而不需要象png图片一样非要存一个alpha通道,并且永远不能变.

    2.  占用内存小,因为一个象素只占用一个byte,所以一般用调色板做一张图片大体只需要原来位图占用内存的一半。

    3.  速度快,这个快有点不绝对,相对的来说,如果游戏使用的图层越多,那么用Graphics.drawImage()肯定就会非常慢。在此我对比我做的一个游戏,在nokia 7610平台,采用8层背景图层,加上大约10个角色贴图,不采用任何的优化算法,耗时100-120ms之间。

    4.  可以完全杜绝j2me的内存出错这个bug。当然,自己必须实现游戏的内存管理。

     

    另外:可能会有人疑问,png图片是经过压缩的,但自己做的调色板完全不用png,那打包的jar文件不就很大么?完全没问题,因为png图片与jar文件的压缩算法都是ziplz77压缩算法,所以当你的txt文件存储进jar中时会进行压缩,压缩比基本上与png一样。

     

    下面说一下我的调色板游戏实现方法:

    J2me平台上,可以用midp2.0Graphics.drawRGB将象素绘画到屏幕上(midp1.0中就只能使用厂商的api了,比如nokiadg.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){}

    }

    };

    一般只能运行大约10fps66007610symbian 7.0平台,N708.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;

          }

        }

     }

    那么可以运行到13fps66007610symbian 7.0平台),速度提升非常客观。

    J2ME移动开发平台搭建篇

    要进行J2ME的开发,首先必须要建立开发的平台,而在开发的平台选择上,有三种方案,在此推荐给大家。

    一、功能比较全的Borland Jbuilder平台
    搭建这个平台,我们必需要安装:JBUILDER 7 或 JBUILDER 8 ,BORLAND 的 MOBILESET 3.1。
    可选材料有:(注意这些不是必须的,没有这些你也可以进行开发)你所想开发的手机SDK,例如要在NOKIA上开发必须准备

    NOKIA DEVELOPER‘S SUITE,还可以根据自己需要加一些模拟器如7210等。
    有了以上的材料就足够我们搭建一个很不错的开发平台了。
    搭建步骤:
    (1):安装JBUILDER,并注册。(注意:D版JBUILDER 8用户,市面上有些D版JBUILDER
    8破解有问题,会导致接下来安装的MOBILESET无法被激活的情况,也就是无论你怎么配置,在MIDP页面里的选项永远是灰的,请勿使用它
    盘中的破解文件,用注册机注册)

    (2):正确安装JBUILDER ,并、成功注册后,安装 MOBILESET 3.1,安装完成后,需要注册,MOBILESET是免费的,你可以向BORLAND索要注册码,也可以用 附录3 中的注册码注册。
    (3):完成以上2步必须步骤后,就可以安装你选装的DEVELOPER'S SUITE和模拟器了(NOKIA SDK安装方法见附录1)。
    (4):正确完成了以上步骤,可以说这个平台已经搭建完成,就这么简单,下面你要做的就是在JBUILDER中NEW 一个PROJECT,在出现

    的窗体中JDK选J2ME的,其他都使用默认的就可以了,完成配置后,再选NEW,这时候在最后的MIDP页面里两个选项应该是可选的,接下

    来你就可以开发了。

    2:Sun 公司官方工具,使用满方便的平台 j2me_wireless_toolkit;
    搭建这个平台,我们必需要安装有:jdk1.4,j2me_wireless_toolkit1。04或j2me_wireless_toolkit2。0 beta1
    可选材料有:(注意这些不是必须的,没有这些你也可以进行开发)你所想开发的手机SDK,例如要在NOKIA上开发必须准备NOKIA
    DEVELOPER‘S SUITE,还可以根据自己需要加一些模拟器如7210等(NOKIA SDK安装方法见附录1)。
    有了以上的材料就足够我们搭建现在的平台。
    (1):首先安装jdk1.4,(在方法一中因为JBUILDER自带JDK所以不需要单独安装。)
    (2):正确安装JDK后,才可以安装j2me_wireless_toolkit,不管1。04还是2。0 BETA1都可以,2个都装也可以。
    (3):完成以上2步必须步骤后,就可以安装你选装的DEVELOPER‘S SUITE和模拟器了(NOKIA SDK安装方法见附录1)。
    (4)正确完成了以上步骤,可以说这个平台已经搭建完毕了,有些菜鸟可能会问这个j2me_wireless_toolkit是干什么的,其实它的作用就和JB

    UILDER差不多,用来编译你写的JAVA程序,但它本身不提供编辑等功能,所以你得用记事本或其他文本编辑软件写程序,使用方法见附录4

    3:个头最小,但用起来比较复杂的平台cldc+MIDP
    搭建这个平台,我们必需要安装:jdk1.4,J2ME_CLDC_ 1.04,MIDP 2.0
    对这个平台的使用方法我自己到现在还不是特别清楚,只粗略的介绍一下
    (1)同样首先要安装jdk1.4
    (2)将J2ME_CLDC_ 1.04,MIDP 2.0和解压到同一目录下如c:\j2me下,其实这两个就是在命令行下的编译器和JBUILDER,toolkit的作用

    一样,但用起来更麻烦。
    (3)详细使用方法见附录5
    介绍完毕,希望能对刚起步的菜鸟有帮助,有什么错误的地方还请大家指正,文章中引用了其他作者的文字,向他们表示感谢。


    附录1:NOKIA SDK安装
    在装完JBUILDER(其实就是看有没有装JDK,JBUILDER自带JDK)或JDK后,NOKIA的DEVELOPER‘S

    SUITE才能被安装,谧巴闐EVELOPER‘S SUITE后装模拟器,一定要装在NOKIA的DEVELOPER‘S SUITE的
    DEVICE目录下,下面是
    NOKIA的DEVELOPER‘S SUITE和一些模拟器的注册码
    nds_jme_v1.1(Nokia Developer Suite”)
    用户名:allyfeng
    序列号:pJzPqsT0PjnMEwaTR2Ga+WiCeSk=
    ns40
    用户名:allyfeng
    序列号:HgaDbt1HpXFucqDp97ThNjvN468=
    7210
    用户名:allyfeng
    序列号:89YPeBKM6tzssXLLi5OxuDdhcyk=
    Nokia 6650模拟器
    注册信息:
    用户名:allyfeng
    序列号:PLkvtJRKbzplqIXRqyb0czF969w=

    附录2:注册机使用方法
    这里我推荐使用JBLicenseGenW.exe
    使用简单,装好JBUILDER后使用,可以注册J7,J8。先生成注册码,在SAVE一下就行。
    对于那些先用试用版注册码,后来再替换的方法我没试过。
    如果运行JBLicenseGenW.exe没反映或出错,可能是你的JBUILDER没装好。我也不知道怎么解决。

    附录3:
    JBuilder MobileSet 3.0.1。需要先安装JBuilder7或JBuilder8。
    注册方法:新建一个文本文件,将下面的注册码复制到文件中,保存。注册时选择Active File,然后
    载入该文件便可。
    注册码:
    -----BEGIN BLOCK-----
    %C5%17%DE%9B%00%00%02I%DE%DAL%
    2C%B2%F7%9DE%80C5%A6%E5%AF%7C%
    A7%06%05%D1%B1%B5%0A%955L%87%E
    5%E6%5B%8C%0D%01%A9%EE%EB-%A9%
    21%7C%E7%8A%E2%1D%B6LZ%E2%F1%F
    B0%E3%7B%1F%F6%E3%9A%3E%E4%1D%
    2B%FD%FB%CD%5C%D6%2BO%FB%F6%89
    %7F%D8j%3E%96%8C%98L%C0%03%15%
    86%D3%FEt%81%1Bf%8F%DD%B6%02%D
    76z%FE%E4%8B%5B%D8%02%1D%BD%F1
    %B0P%A9%27%13%F6%8F%AE%0D%8A%7
    FR%99%ED%93%22%82v%2B%E7%9B%AF
    T%C3Q%1F%8E%CC%BFp%A52%26%DC%9
    F%8EC%D3%1CU%D1%AA%ADb%DA%1B%2
    B%A0%8A%D2i%B3%0C%20%C2%DC%81r
    %E3G%0A%90%E4%B2e%9D%11%3A%F1%
    90%D2_%A0%7BO%C0%A4%A3%17%98%1
    E%21%EE%9D%B3%24%9AK%1A%A5%BE%
    BE%3E%EAg-%F1%B6%9BL%BA-%2F%F8
    %D5%E2%23%C0j%27%E8%B2%ADS%F6t
    %03%C0%D6%E7%3E%E96%28%95%C3%E
    7Z%F4%3EH%B3%B3%D2Y%A9F%16%92%
    93%88%1A%A4mW%85%A1%92i%B0%5BQ
    %A7%EF%87I%D2%7F%3D%8A%A0%A3Y%
    BEQc%EA%8A%8E%08%95%02%7E%9A%F
    F%DBe%80%40%04%8A%DB%BBd%A7g%3
    D%C7%A6%E0%7C%90%29*%EC%E0%ABx
    %D4%29N%D0%DA%A6P%D6%11%1E%ED%
    90%9D%1B%E7S%10%FD%B6%BF%14%A9
    %07P%B9%B0%C1O%9Ds%14%8C%87%99
    e%F7%18%1E%9C%EB%FDc%B4%13a%D9
    %9D%8D%2C%97%1A8%C1%AF%D3x%87%
    7FG%E6%94%98%26%90j%10%C8%EC%8
    64%C2SN%E5%9E%D8T%EFez%BB%8A%D
    1%20%CD5%0B%FC%E3%CC%19%89jv%C
    4%D9%E1r%A2z0%BE%DD%A4j%91h%0D
    %E3%F1%9C%2B%ED%06%60%E1%F2%FA
    X%CA%18F%DE%FB%ABw%93q%29%D5%E
    E%BFF%A4%3E%02%B0%C6%ADH%98p%0
    D%CE%FE%FC%7F%AE%07%04%8E%C7%F
    9d%AD%29%7C%DF%AF%B5V%98%20%1C
    %A5%89%ED%7F%B5RU%EC%AB%FCQ%AF
    Z%5C%F4%9B%A7%5D%8C_%17%D8%CF%
    B1%5B%D6G%28%B2%EE%F8%02%A0%0F
    o%C3%B4%ECG%9E%3D%26%C2%CC%F4e
    %FF_%3C%A5%91%BB%1C%D3%26V%DA%
    F7%95u%BD%3Cf%D9%EE%E7%27%C8%1
    5%3D%E7%A3%9E_%AAR%7C%92%F8%CD
    %13%9D%1E4%9F%84%EFT%8F%5CO%DB
    %B0%D4l%8ChN%83%E4%CE%3F%F32v%
    95%AA%A2f%97p%2F%E5%E5%D8d%91h
    C
    -----END BLOCK-----

    附录4:toolkit用法
    启动工具包,真是说起来容易做起来难,说不定你初此动手的时候就偏偏不知道该如何启动了,OK,那
    就找到KToolbar程序启动它。
    按下Create Project按钮创建新项目。系统提示你输入项目的名字和主MIDlet类的名字,随便你写什么
    都可以,该类应该在启动应用程序时运行

    。工具包会用你输入的项目名为你创建项目目录。
    检查显示的项目属性是否正确,待会儿我们还要回头再检查一下这些设置。
    用记事本编写Java程序源代码(或者拷贝现有的代码)并把程序代码保存到前面KToolbar建立的以你工
    程名命名的目录的src子目录里。
    按下Build按钮编译,之后按下Run按钮在测试模拟器中测试程序。


    附录5:
    首先下载以下软件:
    JDK 1.2或者更高版本 http://java.sun.com/j2se/
    有限连接设备配置(clcdhttp://www.sun.com/software/communitysource/j2me/download.html
    MIDhttp://java.sun.com/products/midp/

    注意:你需要JDK中的JAVAC命令来编译MIDlets。
    下载、解压缩以上软件,放到以下被推荐的目录中:
    C:\JDK1.2
    C:\j2me

    MIDP

    CLCD
    此文章假设目录为C:\j2me

    为了测试MIDP应用程序,你需要安装MIDP和CLCD。

    配置运行环境
    设置环境变量,修改PATH添加MIDP和JDK的工作路径。
    设置环境变量
    设置PATH中的变量,用文本编辑器打开autoexec.bat,或者在开始运行中敲入sysedit命令,并且插入
    以下两行,我们假定你的*作系统和JDK

    全部安装在C盘下。
    SET PATH=%PATH%;%JAVAHOME%\BIN;
    PATH=C:\WINDOWS;C:\WINDOWS\COMMAND;C:\JDK\BIN; C:\j2me\midp\bin;%PATH%
    检查你的环境变量设置是否成功
    在命令行下键入如下命令: c:\midp 回车。
    此时应该弹出一个窗口,如(图1)。
    设置屏幕颜色
    C:\set SCREEN DEPTH=8
    C:\midp -des criptor run.jad 效果见图2
    好了,你现在可以准备测试第一个MIDP了。

    HelloMIDlet的描述文件
    关于HelloMIDlet例子的代码,http://wireless.java.sun.com/midp/articles/intro/ ;查阅。
    MIDlet-Name: HelloMIDlet
    MIDlet-Version: 1.0.0
    MIDlet-Vendor: Sun Microsystems, Inc.
    MIDlet-Des cription: A Simple Example
    MIDlet-Info-URLhttp://java.sun.com/j2me/ ;
    MIDlet-Jar-URL: hello.jar
    MIDlet-Jar-Size: 1063
    MicroEdition-Profile: MIDP-1.0
    MicroEdition-Configuration: CLDC-1.0
    MIDlet-1: HelloMIDlet,, HelloMIDlet

    编译,校验,打包和运行
    编译
    在命令行下键入如下命令(应在一行中实现):
    C:\javac -d .\ -bootclasspath c:\pathTo\MIDP\classes HelloMIDlet.java

    校验
    C:\preverify -classpath c:\j2me\MIDP\classes; C:\Examples\ FirstMIDlet
    一个校验过的CLASS文件被写到目录C:\Examples\output\ 中。
    进入到C:\Examples\output\目录中,键入如下命令:
    C:\Example\output>midp FirstMIDlet
    打包
    把HelloMIDlet.class文件打包成JAR文件。
    C:\jar cf hello.jar HelloMIDlet.class
    运行
    C:\midp -des criptor hello.jad
     
     
     

    精华游戏算法整理

    算法一:A*寻路初探
    From GameDev.net

    译者序:很久以前就知道了A*算法,但是从未认真读过相关的文章,也没有看过代码,只是脑子里有个模糊的概念。这次决定从头开始,研究一下这个被人推崇备至的简单方法,作为学习人工智能的开始。
    这篇文章非常知名,国内应该有不少人翻译过它,我没有查找,觉得翻译本身也是对自身英文水平的锻炼。经过努力,终于完成了文档,也明白的A*算法的原理。毫无疑问,作者用形象的描述,简洁诙谐的语言由浅入深的讲述了这一神奇的算法,相信每个读过的人都会对此有所认识(如果没有,那就是偶的翻译太差了--b)。
    原文链接:http://www.gamedev.net/reference/articles/article2003.asp
    以下是翻译的正文。(由于本人使用ultraedit编辑,所以没有对原文中的各种链接加以处理(除了图表),也是为了避免未经许可链接的嫌疑,有兴趣的读者可以参考原文。

    会者不难,A*(念作A星)算法对初学者来说的确有些难度。

    这篇文章并不试图对这个话题作权威的陈述。取而代之的是,它只是描述算法的原理,使你可以在进一步的阅读中理解其他相关的资料。

    最后,这篇文章没有程序细节。你尽可以用任意的计算机程序语言实现它。如你所愿,我在文章的末尾包含了一个指向例子程序的链接。 压缩包包括C++和Blitz Basic两个语言的版本,如果你只是想看看它的运行效果,里面还包含了可执行文件。

    我们正在提高自己。让我们从头开始。。。

    序:搜索区域

    假设有人想从A点移动到一墙之隔的B点,如下图,绿色的是起点A,红色是终点B,蓝色方块是中间的墙。

    你首先注意到,搜索区域被我们划分成了方形网格。像这样,简化搜索区域,是寻路的第一步。这一方法把搜索区域简化成了一个二维数组。数组的每一个元素是网格的一个方块,方块被标记为可通过的和不可通过的。路径被描述为从A到B我们经过的方块的集合。一旦路径被找到,我们的人就从一个方格的中心走向另一个,直到到达目的地。

    这些中点被称为“节点”。当你阅读其他的寻路资料时,你将经常会看到人们讨论节点。为什么不把他们描述为方格呢?因为有可能你的路径被分割成其他不是方格的结构。他们完全可以是矩形,六角形,或者其他任意形状。节点能够被放置在形状的任意位置-可以在中心,或者沿着边界,或其他什么地方。我们使用这种系统,无论如何,因为它是最简单的。

    开始搜索

    正如我们处理上图网格的方法,一旦搜索区域被转化为容易处理的节点,下一步就是去引导一次找到最短路径的搜索。在A*寻路算法中,我们通过从点A开始,检查相邻方格的方式,向外扩展直到找到目标。

    我们做如下操作开始搜索:


       1,从点A开始,并且把它作为待处理点存入一个“开启列表”。开启列表就像一张购物清单。尽管现在列表里只有一个元素,但以后就会多起来。你的路径可能会通过它包含的方格,也可能不会。基本上,这是一个待检查方格的列表。
       2,寻找起点周围所有可到达或者可通过的方格,跳过有墙,水,或其他无法通过地形的方格。也把他们加入开启列表。为所有这些方格保存点A作为“父方格”。当我们想描述路径的时候,父方格的资料是十分重要的。后面会解释它的具体用途。
       3,从开启列表中删除点A,把它加入到一个“关闭列表”,列表中保存所有不需要再次检查的方格。

    在这一点,你应该形成如图的结构。在图中,暗绿色方格是你起始方格的中心。它被用浅蓝色描边,以表示它被加入到关闭列表中了。所有的相邻格现在都在开启列表中,它们被用浅绿色描边。每个方格都有一个灰色指针反指他们的父方格,也就是开始的方格。

    接着,我们选择开启列表中的临近方格,大致重复前面的过程,如下。但是,哪个方格是我们要选择的呢?是那个F值最低的。

    路径评分

    选择路径中经过哪个方格的关键是下面这个等式:

    F = G + H

    这里:
        * G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
        * H = 从网格上那个方格移动到终点B的预估移动耗费。这经常被称为启发式的,可能会让你有点迷惑。这样叫的原因是因为它只是个猜测。我们没办法事先知道路径的长度,因为路上可能存在各种障碍(墙,水,等等)。虽然本文只提供了一种计算H的方法,但是你可以在网上找到很多其他的方法。

    我们的路径是通过反复遍历开启列表并且选择具有最低F值的方格来生成的。文章将对这个过程做更详细的描述。首先,我们更深入的看看如何计算这个方程。

    正如上面所说,G表示沿路径从起点到当前点的移动耗费。在这个例子里,我们令水平或者垂直移动的耗费为10,对角线方向耗费为14。我们取这些值是因为沿对角线的距离是沿水平或垂直移动耗费的的根号2(别怕),或者约1.414倍。为了简化,我们用10和14近似。比例基本正确,同时我们避免了求根运算和小数。这不是只因为我们怕麻烦或者不喜欢数学。使用这样的整数对计算机来说也更快捷。你不就就会发现,如果你不使用这些简化方法,寻路会变得很慢。

    既然我们在计算沿特定路径通往某个方格的G值,求值的方法就是取它父节点的G值,然后依照它相对父节点是对角线方向或者直角方向(非对角线),分别增加14和10。例子中这个方法的需求会变得更多,因为我们从起点方格以外获取了不止一个方格。

    H值可以用不同的方法估算。我们这里使用的方法被称为曼哈顿方法,它计算从当前格到目的格之间水平和垂直的方格的数量总和,忽略对角线方向。然后把结果乘以10。这被成为曼哈顿方法是因为它看起来像计算城市中从一个地方到另外一个地方的街区数,在那里你不能沿对角线方向穿过街区。很重要的一点,我们忽略了一切障碍物。这是对剩余距离的一个估算,而非实际值,这也是这一方法被称为启发式的原因。想知道更多?你可以在这里找到方程和额外的注解。

    F的值是G和H的和。第一步搜索的结果可以在下面的图表中看到。F,G和H的评分被写在每个方格里。正如在紧挨起始格右侧的方格所表示的,F被打印在左上角,G在左下角,H则在右下角。

    现在我们来看看这些方格。写字母的方格里,G = 10。这是因为它只在水平方向偏离起始格一个格距。紧邻起始格的上方,下方和左边的方格的G值都等于10。对角线方向的G值是14。

    H值通过求解到红色目标格的曼哈顿距离得到,其中只在水平和垂直方向移动,并且忽略中间的墙。用这种方法,起点右侧紧邻的方格离红色方格有3格距离,H值就是30。这块方格上方的方格有4格距离(记住,只能在水平和垂直方向移动),H值是40。你大致应该知道如何计算其他方格的H值了~。

    每个格子的F值,还是简单的由G和H相加得到

    继续搜索

    为了继续搜索,我们简单的从开启列表中选择F值最低的方格。然后,对选中的方格做如下处理:

       4,把它从开启列表中删除,然后添加到关闭列表中。
       5,检查所有相邻格子。跳过那些已经在关闭列表中的或者不可通过的(有墙,水的地形,或者其他无法通过的地形),把他们添加进开启列表,如果他们还不在里面的话。把选中的方格作为新的方格的父节点。
       6,如果某个相邻格已经在开启列表里了,检查现在的这条路径是否更好。换句话说,检查如果我们用新的路径到达它的话,G值是否会更低一些。如果不是,那就什么都不做。
          另一方面,如果新的G值更低,那就把相邻方格的父节点改为目前选中的方格(在上面的图表中,把箭头的方向改为指向这个方格)。最后,重新计算F和G的值。如果这看起来不够清晰,你可以看下面的图示。

    好了,让我们看看它是怎么运作的。我们最初的9格方格中,在起点被切换到关闭列表中后,还剩8格留在开启列表中。这里面,F值最低的那个是起始格右侧紧邻的格子,它的F值是40。因此我们选择这一格作为下一个要处理的方格。在紧随的图中,它被用蓝色突出显示。

     

    首先,我们把它从开启列表中取出,放入关闭列表(这就是他被蓝色突出显示的原因)。然后我们检查相邻的格子。哦,右侧的格子是墙,所以我们略过。左侧的格子是起始格。它在关闭列表里,所以我们也跳过它。

    其他4格已经在开启列表里了,于是我们检查G值来判定,如果通过这一格到达那里,路径是否更好。我们来看选中格子下面的方格。它的G值是14。如果我们从当前格移动到那里,G值就会等于20(到达当前格的G值是10,移动到上面的格子将使得G值增加10)。因为G值20大于14,所以这不是更好的路径。如果你看图,就能理解。与其通过先水平移动一格,再垂直移动一格,还不如直接沿对角线方向移动一格来得简单。

    当我们对已经存在于开启列表中的4个临近格重复这一过程的时候,我们发现没有一条路径可以通过使用当前格子得到改善,所以我们不做任何改变。既然我们已经检查过了所有邻近格,那么就可以移动到下一格了。

    于是我们检索开启列表,现在里面只有7格了,我们仍然选择其中F值最低的。有趣的是,这次,有两个格子的数值都是54。我们如何选择?这并不麻烦。从速度上考虑,选择最后添加进列表的格子会更快捷。这种导致了寻路过程中,在靠近目标的时候,优先使用新找到的格子的偏好。但这无关紧要。(对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径。)

    那我们就选择起始格右下方的格子,。

     

    这次,当我们检查相邻格的时候,发现右侧是墙,于是略过。上面一格也被略过。我们也略过了墙下面的格子。为什么呢?因为你不能在不穿越墙角的情况下直接到达那个格子。你的确需要先往下走然后到达那一格,按部就班的走过那个拐角。(注解:穿越拐角的规则是可选的。它取决于你的节点是如何放置的。)

    这样一来,就剩下了其他5格。当前格下面的另外两个格子目前不在开启列表中,于是我们添加他们,并且把当前格指定为他们的父节点。其余3格,两个已经在开启列表中(起始格,和当前格上方的格子,在表格中蓝色高亮显示),于是我们略过它们。最后一格,在当前格的左侧,将被检查通过这条路径,G值是否更低。不必担心,我们已经准备好检查开启列表中的下一格了。

    我们重复这个过程,知道目标格被添加进开启列表,就如在下面的图中所看到的。

    IMG upload/forum/200562132741.jpg[/IMG]
    [图6]

    注意,起始格下方格子的父节点已经和前面不同的。之前它的G值是28,并且指向右上方的格子。现在它的G值是20,指向它上方的格子。这在寻路过程中的某处发生,当应用新路径时,G值经过检查变得低了-于是父节点被重新指定,G和F值被重新计算。尽管这一变化在这个例子中并不重要,在很多场合,这种变化会导致寻路结果的巨大变化。

    那么,我们怎么确定这条路径呢?很简单,从红色的目标格开始,按箭头的方向朝父节点移动。这最终会引导你回到起始格,这就是你的路径!看起来应该像图中那样。从起始格A移动到目标格B只是简单的从每个格子(节点)的中点沿路径移动到下一个,直到你到达目标点。就这么简单。

    IMG upload/forum/200562132747.jpg[/IMG]
    [图7]

    A*方法总结

    好,现在你已经看完了整个说明,让我们把每一步的操作写在一起:

       1,把起始格添加到开启列表。
       2,重复如下的工作:
          a) 寻找开启列表中F值最低的格子。我们称它为当前格。
          b) 把它切换到关闭列表。
          c) 对相邻的8格中的每一个?
              * 如果它不可通过或者已经在关闭列表中,略过它。反之如下。
              * 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。
              * 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。更低的G值意味着更好的路径。如果是这样,就把这一格的父节点改成当前格,并且重新计算这一格的G和F值。如果你保持你的开启列表按F值排序,改变之后你可能需要重新对开启列表排序。

          d) 停止,当你
              * 把目标格添加进了开启列表,这时候路径被找到,或者
              * 没有找到目标格,开启列表已经空了。这时候,路径不存在。
       3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是你的路径。

    题外话

    离题一下,见谅,值得一提的是,当你在网上或者相关论坛看到关于A*的不同的探讨,你有时会看到一些被当作A*算法的代码而实际上他们不是。要使用A*,你必须包含上面讨论的所有元素--特定的开启和关闭列表,用F,G和H作路径评价。有很多其他的寻路算法,但他们并不是A*,A*被认为是他们当中最好的。Bryan Stout在这篇文章后面的参考文档中论述了一部分,包括他们的一些优点和缺点。有时候特定的场合其他算法会更好,但你必须很明确你在作什么。好了,够多的了。回到文章。

    实现的注解

    现在你已经明白了基本原理,写你的程序的时候还得考虑一些额外的东西。下面这些材料中的一些引用了我用C++和Blitz Basic写的程序,但对其他语言写的代码同样有效。

    1,维护开启列表:这是A*寻路算法最重要的组成部分。每次你访问开启列表,你都需要寻找F值最低的方格。有几种不同的方法实现这一点。你可以把路径元素随意保存,当需要寻找F值最低的元素的时候,遍历开启列表。这很简单,但是太慢了,尤其是对长路径来说。这可以通过维护一格排好序的列表来改善,每次寻找F值最低的方格只需要选取列表的首元素。当我自己实现的时候,这种方法是我的首选。

    在小地图。这种方法工作的很好,但它并不是最快的解决方案。更苛求速度的A*程序员使用叫做“binary heap”的方法,这也是我在代码中使用的方法。凭我的经验,这种方法在大多数场合会快2~3倍,并且在长路经上速度呈几何级数提升(10倍以上速度)。如果你想了解更多关于binary heap的内容,查阅我的文章,Using Binary Heaps in A* Pathfinding。

    2,其他单位:如果你恰好看了我的例子代码,你会发现它完全忽略了其他单位。我的寻路者事实上可以相互穿越。取决于具体的游戏,这也许可以,也许不行。如果你打算考虑其他单位,希望他们能互相绕过,我建议在寻路算法中忽略其他单位,写一些新的代码作碰撞检测。当碰撞发生,你可以生成一条新路径或者使用一些标准的移动规则(比如总是向右,等等)直到路上没有了障碍,然后再生成新路径。为什么在最初的路径计算中不考虑其他单位呢?那是因为其他单位会移动,当你到达他们原来的位置的时候,他们可能已经离开了。这有可能会导致奇怪的结果,一个单位突然转向,躲避一个已经不在那里的单位,并且会撞到计算完路径后,冲进它的路径中的单位。

    然而,在寻路算法中忽略其他对象,意味着你必须编写单独的碰撞检测代码。这因游戏而异,所以我把这个决定权留给你。参考文献列表中,Bryan Stout的文章值得研究,里面有一些可能的解决方案(像鲁棒追踪,等等)。

    3,一些速度方面的提示:当你开发你自己的A*程序,或者改写我的,你会发现寻路占据了大量的CPU时间,尤其是在大地图上有大量对象在寻路的时候。如果你阅读过网上的其他材料,你会明白,即使是开发了星际争霸或帝国时代的专家,这也无可奈何。如果你觉得寻路太过缓慢,这里有一些建议也许有效:

        * 使用更小的地图或者更少的寻路者。
        * 不要同时给多个对象寻路。取而代之的是把他们加入一个队列,把寻路过程分散在几个游戏周期中。如果你的游戏以40周期每秒的速度运行,没人能察觉。但是他们会发觉游戏速度突然变慢,当大量寻路者计算自己路径的时候。
        * 尽量使用更大的地图网格。这降低了寻路中搜索的总网格数。如果你有志气,你可以设计两个或者更多寻路系统以便使用在不同场合,取决于路径的长度。这也正是专业人士的做法,用大的区域计算长的路径,然后在接近目标的时候切换到使用小格子/区域的精细寻路。如果你对这个观点感兴趣,查阅我的文章Two-Tiered A* Pathfinding。
        * 使用路径点系统计算长路径,或者预先计算好路径并加入到游戏中。
        * 预处理你的地图,表明地图中哪些区域是不可到达的。我把这些区域称作“孤岛”。事实上,他们可以是岛屿或其他被墙壁包围等无法到达的任意区域。A*的下限是,当你告诉它要寻找通往那些区域的路径时,它会搜索整个地图,直到所有可到达的方格/节点都被通过开启列表和关闭列表的计算。这会浪费大量的CPU时间。可以通过预先确定这些区域(比如通过flood-fill或类似的方法)来避免这种情况的发生,用某些种类的数组记录这些信息,在开始寻路前检查它。在我Blitz版本的代码中,我建立了一个地图预处理器来作这个工作。它也标明了寻路算法可以忽略的死端,这进一步提高了寻路速度。

    4,不同的地形损耗:在这个教程和我附带的程序中,地形只有两种-可通过的和不可通过的。但是你可能会需要一些可通过的地形,但是移动耗费更高-沼泽,小山,地牢的楼梯,等等。这些都是可通过但是比平坦的开阔地移动耗费更高的地形。类似的,道路应该比自然地形移动耗费更低。

    这个问题很容易解决,只要在计算任何地形的G值的时候增加地形损耗就可以了。简单的给它增加一些额外的损耗就可以了。由于A*算法已经按照寻找最低耗费的路径来设计,所以很容易处理这种情况。在我提供的这个简单的例子里,地形只有可通过和不可通过两种,A*会找到最短,最直接的路径。但是在地形耗费不同的场合,耗费最低的路径也许会包含很长的移动距离-就像沿着路绕过沼泽而不是直接穿过它。

    一种需额外考虑的情况是被专家称之为“influence mapping”的东西(暂译为影响映射图)。就像上面描述的不同地形耗费一样,你可以创建一格额外的分数系统,并把它应用到寻路的AI中。假设你有一张有大批寻路者的地图,他们都要通过某个山区。每次电脑生成一条通过那个关口的路径,它就会变得更拥挤。如果你愿意,你可以创建一个影响映射图对有大量屠杀事件的格子施以不利影响。这会让计算机更倾向安全些的路径,并且帮助它避免总是仅仅因为路径短(但可能更危险)而持续把队伍和寻路者送到某一特定路径。

    5,处理未知区域:你是否玩过这样的PC游戏,电脑总是知道哪条路是正确的,即使它还没有侦察过地图?对于游戏,寻路太好会显得不真实。幸运的是,这是一格可以轻易解决的问题。

    答案就是为每个不同的玩家和电脑(每个玩家,而不是每个单位--那样的话会耗费大量的内存)创建一个独立的“knownWalkability”数组,每个数组包含玩家已经探索过的区域,以及被当作可通过区域的其他区域,直到被证实。用这种方法,单位会在路的死端徘徊并且导致错误的选择直到他们在周围找到路。一旦地图被探索了,寻路就像往常那样进行。

    6,平滑路径:尽管A*提供了最短,最低代价的路径,它无法自动提供看起来平滑的路径。看一下我们的例子最终形成的路径(在图7)。最初的一步是起始格的右下方,如果这一步是直接往下的话,路径不是会更平滑一些吗?

    有几种方法来解决这个问题。当计算路径的时候可以对改变方向的格子施加不利影响,对G值增加额外的数值。也可以换种方法,你可以在路径计算完之后沿着它跑一遍,找那些用相邻格替换会让路径看起来更平滑的地方。想知道完整的结果,查看Toward More Realistic Pathfinding,一篇(免费,但是需要注册)Marco Pinter发表在Gamasutra.com的文章

    7,非方形搜索区域:在我们的例子里,我们使用简单的2D方形图。你可以不使用这种方式。你可以使用不规则形状的区域。想想冒险棋的游戏,和游戏中那些国家。你可以设计一个像那样的寻路关卡。为此,你可能需要建立一个国家相邻关系的表格,和从一个国家移动到另一个的G值。你也需要估算H值的方法。其他的事情就和例子中完全一样了。当你需要向开启列表中添加新元素的时候,不需使用相邻的格子,取而代之的是从表格中寻找相邻的国家。

    类似的,你可以为一张确定的地形图创建路径点系统,路径点一般是路上,或者地牢通道的转折点。作为游戏设计者,你可以预设这些路径点。两个路径点被认为是相邻的如果他们之间的直线上没有障碍的话。在冒险棋的例子里,你可以保存这些相邻信息在某个表格里,当需要在开启列表中添加元素的时候使用它。然后你就可以记录关联的G值(可能使用两点间的直线距离),H值(可以使用到目标点的直线距离),其他都按原先的做就可以了。

    另一个在非方形区域搜索RPG地图的例子,查看我的文章Two-Tiered A* Pathfinding。

    进一步的阅读

    好,现在你对一些进一步的观点有了初步认识。这时,我建议你研究我的源代码。包里面包含两个版本,一个是用C++写的,另一个用Blitz Basic。顺便说一句,两个版本都注释详尽,容易阅读,这里是链接。

        * 例子代码:A* Pathfinder (2D) Version 1.71

    如果你既不用C++也不用Blitz Basic,在C++版本里有两个小的可执行文件。Blitz Basic可以在从Blitz Basic网站免费下载的litz Basic 3D(不是Blitz Plus)演示版上运行。Ben O&#39;Neill提供一个联机演示可以在这里找到。

    你也该看看以下的网页。读了这篇教程后,他们应该变得容易理解多了。

        * Amit的 A* 页面:这是由Amit Patel制作,被广泛引用的页面,如果你没有事先读这篇文章,可能会有点难以理解。值得一看。尤其要看Amit关于这个问题的自己的看法。
        * Smart Moves:智能寻路:Bryan Stout发表在Gamasutra.com的这篇文章需要注册才能阅读。注册是免费的而且比起这篇文章和网站的其他资源,是非常物有所值的。Bryan用Delphi写的程序帮助我学习A*,也是我的A*代码的灵感之源。它还描述了A*的几种变化。
        * 地形分析:这是一格高阶,但是有趣的话题,Dave Pottinge撰写,Ensemble Studios的专家。这家伙参与了帝国时代和君王时代的开发。别指望看懂这里所有的东西,但是这是篇有趣的文章也许会让你产生自己的想法。它包含一些对mip-mapping,influence mapping以及其他一些高级AI/寻路观点。对"flood filling"的讨论使我有了我自己的“死端”和“孤岛”的代码的灵感,这些包含在我Blitz版本的代码中。

    其他一些值得一看的网站:

        * aiGuru: Pathfinding
        * Game AI Resource: Pathfinding
        * GameDev.net: Pathfinding

    好了,这就是全部。如果你刚好写一个运用这些观点的程序,我想见识见识。你可以这样联系我:
    现在,好运

    -----------------------------------------------------------------------------
     
    碰撞

    1.   碰撞检测和响应

     

    碰撞在游戏中运用的是非常广泛的,运用理论实现的碰撞,再加上一些小技巧,可以让碰撞检测做得非常精确,效率也非常高。从而增加游戏的功能和可玩性。

    2D碰撞检测

    2D的碰撞检测已经非常稳定,可以在许多著作和论文中查询到。3D的碰撞还没有找到最好的方法,现在使用的大多数方法都是建立在2D基础上的。

    碰撞检测

    碰撞的检测不仅仅是运用在游戏中,事实上,一开始的时候是运用在模拟和机器人技术上的。这些工业上的碰撞检测要求非常高,而碰撞以后的响应也是需要符合现实生活的,是需要符合人类常规认识的。游戏中的碰撞有些许的不一样,况且,更重要的,我们制作的东西充其量是商业级别,还不需要接触到纷繁复杂的数学公式。

    IMG upload/forum/200562133540.jpg[/IMG]
    图1


    最理想的碰撞,我想莫过于上图,完全按照多边形的外形和运行路径规划一个范围,在这个范围当中寻找会产生阻挡的物体,不管是什么物体,产生阻挡以后,我们运动的物体都必须在那个位置产生一个碰撞的事件。最美好的想法总是在实现上有一些困难,事实上我们可以这么做,但是效率却是非常非常低下的,游戏中,甚至于工业中无法忍受这种速度,所以我们改用其它的方法来实现。


    IMG upload/forum/200562133545.jpg[/IMG]
    图2

    最简单的方法如上图,我们寻找物体的中心点,然后用这个中心点来画一个圆,如果是一个3D的物体,那么我们要画的就是一个球体。在检测物体碰撞的时候,我们只要检测两个物体的半径相加是否大于这两个物体圆心的实际距离。


    IMG upload/forum/200562133550.jpg[/IMG]
    图3

    这个算法是最简单的一种,现在还在用,但是不是用来做精确的碰撞检测,而是用来提高效率的模糊碰撞检测查询,到了这个范围以后,再进行更加精密的碰撞检测。一种比较精密的碰撞检测查询就是继续这种画圆的思路,然后把物体细分,对于物体的每个部件继续画圆,然后再继续进行碰撞检测,直到系统规定的,可以容忍的误差范围以后才触发碰撞事件,进行碰撞的一些操作。

    有没有更加简单的方法呢?2D游戏中有许多图片都是方方正正的,所以我们不必把碰撞的范围画成一个圆的,而是画成一个方的。这个正方形,或者说是一个四边形和坐标轴是对齐的,所以运用数学上的一些方法,比如距离计算等还是比较方便的。这个检测方法就叫AABBs(Axis-aligned Bounding Boxes)碰撞检测,游戏中已经运用的非常广泛了,因为其速度快,效率高,计算起来非常方便,精确度也是可以忍受的。

     

    做到这一步,许多游戏的需求都已经满足了。但是,总是有人希望近一步优化,而且方法也是非常陈旧的:继续对物体的各个部分进行细分,对每个部件做AABB的矩形,那这个优化以后的系统就叫做OBB系统。虽然说这个优化以后的系统也不错,但是,许多它可以运用到的地方,别人却不爱使用它,这是后面会继续介绍的地方。

     

    John Carmack不知道看的哪本书,他早在DOOM中已经使用了BSP系统(二分空间分割),再加上一些小技巧,他的碰撞做得就非常好了,再加上他发明的castray算法,DOOM已经不存在碰撞的问题,解决了这样的关键技术,我想他不再需要在什么地方分心了,只要继续研究渲染引擎就可以了。(Windows游戏编程大师技巧P392~P393介绍)(凸多边形,多边形退化,左手定律)SAT系统非常复杂,是SHT(separating hyperplane theorem,分离超平面理论)的一种特殊情况。这个理论阐述的就是两个不相关的曲面,是否能够被一个超平面所分割开来,所谓分割开来的意思就是一个曲面贴在平面的一边,而另一个曲面贴在平面的另一边。我理解的就是有点像相切的意思。SAT是SHT的特殊情况,所指的就是两个曲面都是一些多边形,而那个超平面也是一个多边形,这个超平面的多边形可以在场景中的多边形列表中找到,而超平面可能就是某个多边形的表面,很巧的就是,这个表面的法线和两个曲面的切面是相对应的。接下来的证明,我想是非常复杂的事情,希望今后能够找到源代码直接运用上去。而我们现在讲究的快速开发,我想AABB就足以满足了。

    3D碰撞检测

    3D的检测就没有什么很标准的理论了,都建立在2D的基础上,我们可以沿用AABB或者OBB,或者先用球体做粗略的检测,然后用AABB和OBB作精细的检测。BSP技术不流行,但是效率不错。微软提供了D3DIntersect函数让大家使用,方便了许多,但是和通常一样,当物体多了以后就不好用了,明显的就是速度慢许多。

    碰撞反应

    碰撞以后我们需要做一些反应,比如说产生反冲力让我们反弹出去,或者停下来,或者让阻挡我们的物体飞出去,或者穿墙,碰撞最讨厌的就是穿越,本来就不合逻辑,查阅了那么多资料以后,从来没有看到过需要穿越的碰撞,有摩擦力是另外一回事。首先看看弹性碰撞。弹性碰撞就是我们初中物理中说的动量守恒。物体在碰撞前后的动量守恒,没有任何能量损失。这样的碰撞运用于打砖块的游戏中。引入质量的话,有的物体会是有一定的质量,这些物体通常来说是需要在碰撞以后进行另外一个方向的运动的,另外一些物体是设定为质量无限大的,这些物体通常是碰撞墙壁。

    当物体碰到质量非常大的物体,默认为碰到了一个弹性物体,其速度会改变,但是能量不会受到损失。一般在代码上的做法就是在速度向量上加上一个负号。

    绝对的弹性碰撞是很少有的,大多数情况下我们运用的还是非弹性碰撞。我们现在玩的大多数游戏都用的是很接近现实的非弹性碰撞,例如Pain-Killer中的那把吸力枪,它弹出去的子弹吸附到NPC身上时的碰撞响应就是非弹性碰撞;那把残忍的分尸刀把墙打碎的初始算法就是一个非弹性碰撞,其后使用的刚体力学就是先建立在这个算法上的。那么,是的,如果需要非弹性碰撞,我们需要介入摩擦力这个因素,而我们也无法简单使用动量守恒这个公式。

    我们可以采取比较简单的方法,假设摩擦系数μ非常大,那么只要物体接触,并且拥有一个加速度,就可以产生一个无穷大的摩擦力,造成物体停止的状态。

    基于别人的引擎写出一个让自己满意的碰撞是不容易的,那么如果自己建立一个碰撞系统的话,以下内容是无法缺少的:

    &#8226;         一个能够容忍的碰撞系统

    –     一个从概念上可以接受的物理系统

    –     质量

    –     速度

    –     摩擦系数

    –     地心引力
     
    --------------------------------------------------------------------------------
    三、寻路算法新思维

    目前常用寻路算法是A*方式,原理是通过不断搜索逼近目的地的路点来获得。

    如果通过图像模拟搜索点,可以发现:非启发式的寻路算法实际上是一种穷举法,通过固定顺序依次搜索人物周围的路点,直到找到目的地,搜索点在图像上的表现为一个不断扩大的矩形。如下:
         
    IMG upload/forum/200562134117.jpg[/IMG]
    IMG upload/forum/200562134121.jpg[/IMG]

    很快人们发现如此穷举导致搜索速度过慢,而且不是很符合逻辑,试想:如果要从(0,0)点到达(100,0)点,如果每次向东搜索时能够走通,那么干吗还要搜索其他方向呢?所以,出现了启发式的A*寻路算法,一般通过 已经走过的路程 + 到达目的地的直线距离 代价值作为搜索时的启发条件,每个点建立一个代价值,每次搜索时就从代价低的最先搜索,如下:

    IMG upload/forum/200562134126.jpg[/IMG]
    IMG upload/forum/200562134130.jpg[/IMG]
         
    综上所述,以上的搜索是一种矩阵式的不断逼近终点的搜索做法。优点是比较直观,缺点在于距离越远、搜索时间越长。

    现在,我提出一种新的AI寻路方式——矢量寻路算法。

    通过观察,我们可以发现,所有的最优路线,如果是一条折线,那么、其每一个拐弯点一定发生在障碍物的突出边角,而不会在还没有碰到障碍物就拐弯的情况:如下图所示:

    IMG upload/forum/200562134135.jpg[/IMG]

    我们可以发现,所有的红色拐弯点都是在障碍物(可以认为是一个凸多边形)的顶点处,所以,我们搜索路径时,其实只需要搜索这些凸多边形顶点不就可以了吗?如果将各个顶点连接成一条通路就找到了最优路线,而不需要每个点都检索一次,这样就大大减少了搜索次数,不会因为距离的增大而增大搜索时间。

    这种思路我尚未将其演变为算法,姑且提出一个伪程序给各位参考:
    1.        建立各个凸多边形顶点的通路表TAB,表示顶点A到顶点B是否可达,将可达的顶点分组保存下来。如: ( (0,0) (100,0) ),这一步骤在程序刚开始时完成,不要放在搜索过程中空耗时间。
    2.        开始搜索A点到B点的路线
    3.        检测A点可以直达凸多边形顶点中的哪一些,挑选出最合适的顶点X1。
    4.        检测与X1相连(能够接通)的有哪些顶点,挑出最合适的顶点X2。
    5.        X2是否是终点B?是的话结束,否则转步骤4(X2代入X1)

    如此下来,搜索只发生在凸多边形的顶点,节省了大量的搜索时间,而且找到的路线无需再修剪锯齿,保证了路线的最优性。

    这种方法搜索理论上可以减少大量搜索点、缺点是需要实现用一段程序得出TAB表,从本质上来说是一种空间换时间的方法,而且搜索时A*能够用的启发条件,在矢量搜索时依然可以使用。
     
     

    ----------------------------------------------------------------------------- 
    四、战略游戏中的战争模型算法的初步探讨

     
      《三国志》系列游戏相信大家都有所了解,而其中的(宏观)战斗时关于双方兵力,士气,兵种克制,攻击力,增援以及随战争进行兵力减少等数值的算法是十分值得研究的。或许是由于简单的缘故,我在网上几乎没有找到相关算法的文章。下面给出这个战争的数学模型算法可以保证游戏中战争的游戏性与真实性兼顾,希望可以给有需要这方面开发的人一些启迪。
    假设用x(t)和y(t)表示甲乙交战双方在t时刻的兵力,如果是开始时可视为双方士兵人数。

      假设每一方的战斗减员率取决于双方兵力和战斗力,用f(x,y)和g(x,y)表示,每一方的增援率是给定函数用u(t)和v(t)表示。

      如果双方用正规部队作战(可假设是相同兵种),先分析甲方的战斗减员率f(x,y)。可知甲方士兵公开活动,处于乙方没一个士兵的监视和杀伤范围之内,一但甲方的某个士兵被杀伤,乙方的火力立即集中在其余士兵身上,所以甲方的战斗减员率只与乙方的兵力有关可射为f与y成正比,即f=ay,a表示乙方平均每个士兵对甲方士兵的杀伤率(单位时间的杀伤数),成为乙方的战斗有效系数。类似g= -bx
    这个战争模型模型方程1为

    x’(t)= -a*y(t)+u(t) x’(t)是x(t)对于t 的导数
    y’(t)= -b*x(t)+v(t) y’(t)是y(t)对于t的导数

    利用给定的初始兵力,战争持续时间,和增援兵力可以求出双方兵力在战争中的变化函数。
    (本文中解法略)

    如果考虑由于士气和疾病等引起的非战斗减员率(一般与本放兵力成正比,设甲乙双方分别为h,w)

    可得到改进战争模型方程2:

    x’(t)= -a*y(t)-h*x(t)+u(t)
    y’(t)= -b*x(t)-w*y(t)+v(t)

    利用初始条件同样可以得到双方兵力在战争中的变化函数和战争结果。

    此外还有不同兵种作战(兵种克制)的数学模型:
    模型1中的战斗有效系数a可以进一步分解为a=ry*py*(sry/sx),其中ry是乙方的攻击率(每个士兵单位的攻击次数),py是每次攻击的命中率。(sry/sx)是乙方攻击的有效面积sry与甲方活动范围sx之比。类似甲方的战斗有效系数b=rx*px*(srx/sy),rx和px是甲方的攻击率和命中率,(srx/sy)是甲方攻击的有效面积与乙方活动范围sy之比。由于增加了兵种克制的攻击范围,所以战斗减员率不光与对方兵力有关,而且随着己放兵力增加而增加。因为在一定区域内,士兵越多被杀伤的就越多。

    方程
    x’(t)= -ry*py*(sry/sx)*x(t)*y(t)-h*x(t)+u(t)
    y’(t)= -rx*px*(srx/sy)*x(t)*y(t)-w*y(t)+u(t) 
                

    -----------------------------------------------------------------------------


     
    飞行射击游戏中的碰撞检测    

      在游戏中物体的碰撞是经常发生的,怎样检测物体的碰撞是一个很关键的技术问题。在RPG游戏中,一般都将场景分为许多矩形的单元,碰撞的问题被大大的简化了,只要判断精灵所在的单元是不是有其它的东西就可以了。而在飞行射击游戏(包括象荒野大镖客这样的射击游戏)中,碰撞却是最关键的技术,如果不能很好的解决,会影响玩游戏者的兴趣。因为飞行射击游戏说白了就是碰撞的游戏——躲避敌人的子弹或飞机,同时用自己的子弹去碰撞敌人。

      碰撞,这很简单嘛,只要两个物体的中心点距离小于它们的半径之和就可以了。确实,而且我也看到很多人是这样做的,但是,这只适合圆形的物体——圆形的半径处处相等。如果我们要碰撞的物体是两艘威力巨大的太空飞船,它是三角形或矩形或其他的什么形状,就会出现让人尴尬的情景:两艘飞船眼看就要擦肩而过,却出人意料的发生了爆炸;或者敌人的子弹穿透了你的飞船的右弦,你却安然无恙,这不是我们希望发生的。于是,我们需要一种精确的检测方法。

      那么,怎样才能达到我们的要求呢?其实我们的前辈们已经总结了许多这方面的经验,如上所述的半径检测法,三维中的标准平台方程法,边界框法等等。大多数游戏程序员都喜欢用边界框法,这也是我采用的方法。边界框是在编程中加进去的不可见的边界。边界框法,顾名思义,就是用边界框来检测物体是否发生了碰撞,如果两个物体的边界框相互干扰,则发生了碰撞。用什么样的边界框要视不同情况而定,用最近似的几何形状。当然,你可以用物体的准确几何形状作边界框,但出于效率的考虑,我不赞成这样做,因为游戏中的物体一般都很复杂,用复杂的边界框将增加大量的计算,尤其是浮点计算,而这正是我们想尽量避免的。但边界框也不能与准确几何形状有太大的出入,否则就象用半径法一样出现奇怪的现象。

      在飞行射击游戏中,我们的飞机大多都是三角形的,我们可以用三角形作近似的边界框。现在我们假设飞机是一个正三角形(或等要三角形,我想如果谁把飞机设计成左右不对称的怪物,那他的审美观一定有问题),我的飞机是正着的、向上飞的三角形,敌人的飞机是倒着的、向下飞的三角形,且飞机不会旋转(大部分游戏中都是这样的)。我们可以这样定义飞机:中心点O(Xo,Yo),三个顶点P0(X0,Y0)、P1(X1,Y1)、P2(X2,Y2)。中心点为正三角形的中心点,即中心点到三个顶点的距离相等。接下来的问题是怎样确定两个三角形互相干扰了呢?嗯,现在我们接触到问题的实质了。如果你学过平面解析几何,我相信你可以想出许多方法解决这个问题。判断一个三角形的各个顶点是否在另一个三角形里面,看起来是个不错的方法,你可以这样做,但我却发现一个小问题:一个三角形的顶点没有在另一个三角形的里面,却可能发生了碰撞,因为另一个三角形的顶点在这个三角形的里面,所以要判断两次,这很麻烦。有没有一次判断就可以的方法?我们把三角形放到极坐标平面中,中心点为原点,水平线即X轴为零度角。我们发现三角形成了这个样子:在每个角度我们都可以找到一个距离,用以描述三角形的边。既然我们找到了边到中心点的距离,那就可以用这个距离来检测碰撞。如图一,两个三角形中心点坐标分别为(Xo,Yo)和(Xo1,Yo1),由这两个点的坐标求出两点的距离及两点连线和X轴的夹角θ,再由θ求出中心点连线与三角形边的交点到中心点的距离,用这个距离与两中心点距离比较,从而判断两三角形是否碰撞。因为三角形左右对称,所以θ取-90~90度区间就可以了。哈,现在问题有趣多了,-90~90度区间正是正切函数的定义域,求出θ之后再找对应的边到中心点的距离就容易多了,利用几何知识,如图二,将三角形的边分为三部分,即图2中红绿蓝三部分,根据θ在那一部分而分别对待。用正弦定理求出边到中心点的距离,即图2中浅绿色线段的长度。但是,如果飞机每次移动都这样判断一次,效率仍然很低。我们可以结合半径法来解决,先用半径法判断是否可能发生碰撞,如果可能发生碰撞,再用上面的方法精确判断是不是真的发生了碰撞,这样基本就可以了。如果飞机旋转了怎么办呢,例如,如图三所示飞机旋转了一个角度α,仔细观察图三会发现,用(θ-α)就可以求出边到中心点的距离,这时你要注意边界情况,即(θ-α)可能大于90度或小于-90度。啰罗嗦嗦说了这么多,不知道大家明白了没有。我编写了一个简单的例程,用于说明我的意图。在例子中假设所有飞机的大小都一样,并且没有旋转。

    IMG upload/forum/200562134623.gif[/IMG]
    IMG upload/forum/200562134627.gif[/IMG]
    IMG upload/forum/200562134632.gif[/IMG]

    /////////////////////////////////////////////////////////////////////
    //example.cpp
    //碰撞检测演示
    //作者 李韬
    /////////////////////////////////////////////////////////////////////
    //限于篇幅,这里只给出了碰撞检测的函数
    //define/////////////////////////////////////////////////////////////
    #define NUM_VERTICES 3
    #define ang_30 -0.5236
    #define ang60  1.0472
    #define ang120 2.0944
    //deftype////////////////////////////////////////////////////////////

    struct object
    {
        float xo, yo;
        float radio;
        float x_vel, y_vel;
        float vertices[NUM_VERTICES][2];
    }

    //faction/////////////////////////////////////////////////////////////
    //根据角度求距离
    float AngToDis(struct object obj, float angle)
    {
        float dis, R;
        R = obj.radius;
        if (angle <= ang_30)
            dis = R / (2 * sin(-angle));
        else if (angle >= 0)
            dis = R / (2 * sin(angle + ang60));
        else dis = R / (2 * sin(ang120 - angle));
        return dis;
    }

    //碰撞检测
    int CheckHit(struct object obj1, struct object obj2)
    {
        float deltaX, deltaY, angle, distance, bumpdis;
        deltaX = abs(obj1.xo - obj2.xo);
        deltaY = obj1.yo - obj2.yo;
        distance = sqrt(deltaX * deltaX + deltaY * deltaY);
        if (distance <= obj.radio)
        {
             angle = atan2(deltaY, deltaX);
             bumpdis1 = AngToDis(obj1, angle);
             return (distance <= 2 * bumpdis);
        }
        ruturn 0;
    }
    //End//////////////////////////////////////////////////////////////

      上面程序只是用于演示,并不适合放在游戏中,但你应该明白它的意思,以便写出适合你自己的碰撞检测。游戏中的情况是多种多样的,没有哪种方法能适应所有情况,你一定能根据自己的情况找到最适合自己的方法。
     
     

    -----------------------------------------------------------------------------


     
    高级碰撞检测技术

    高级碰撞检测技术 第一部分
    Advanced Collision Detection Techniques

    这文章原载于Gamasutra,共有三部分。我想将它翻译,请大家指教。

    http://www.gamasutra.com/features/20000330/bobic_01.htm
    http://www.gamasutra.com/features/20000330/bobic_02.htm
    http://www.gamasutra.com/features/20000330/bobic_03.htm


    / 1 ………………………………………………………………………………………………….
    自从电脑游戏降临以来,程序员们不断地设计各种方法去模拟现实的世界。例如Pong(著名的碰球游戏),展示了一个动人的场面(一个球及两根摆绳)。当玩家将拽住摆绳移动到一定高度的,然后放开球,球就会离开玩家向对手冲去。以今天的标准,这样的基础操作也许就是原始碰撞检测的起源。现在的电脑游戏比以前的Pong复杂多了,而且更多是基于3D的。这也使3D碰撞检测的困难要远远高于一个简单的2D Pong。一些较早的飞行模拟游戏说明了糟糕的碰撞检测技术是怎样破坏一个游戏。如:当你的飞机撞到一座山峰的时候,你居然还可以安全的幸存下来,这在现实中是不可能发生的。甚至最近刚出的一些游戏也存在此类问题。许多玩家对他们喜爱的英雄或是女英雄部分身体居然可以穿过墙而感到失望。甚至更坏的是玩家被一颗没有和他发生碰撞关系的火箭击中。因为今天的玩家要求增加唯实论的要求越来越高,我们游戏开发者们将尽可能在我们的游戏世界做一些改进以便接近真实的世界。
      Since the advent of computer games, programmers have continually devised ways to simulate the world more precisely. Pong, for instance, featured a moving square (a ball) and two paddles. Players had to move the paddles to an appropriate position at an appropriate time, thus rebounding the ball toward the opponent and away from the player. The root of this basic operation is primitive(by today’s standards) collision detection. Today’s games are much more advanced than Pong, and most are based in 3D. Collision detection in 3D is many magnitudes more difficult to implement than a simple 2D Pong game. The experience of playing some of the early flight simulators illustrated how bad collision detection can ruin a game. Flying through a mountain peak and surviving isn’t very realistic. Even some recent games have exhibited collision problems. Many game players have been disappointed by the sight of their favorite heroes or heroines with parts of their bodies inside rigid walls. Even worse, many players have had the experience of being hit by a rocket or bullet that was “not even close” to them. Because today’s players demand increasing levels of realism, we developers will have to do some hard thinking in order to approximate the real world in our game worlds as closely as possible.

    / 2 …………………………………………………………………………………………………
    这篇碰撞检测的论文会使用一些基础的几何学及数学知识。在文章的结束,我也会提供一些参考文献给你。我假定你已经读过Jeff Lander写的图形教程中的碰撞检测部分(“Crashing into the New Year,” ; “When Two Hearts Collide,”; and “Collision Response: Bouncy, Trouncy, Fun,” )。我将给你一些图片让你能快速的联系起核心例程。我们将要讨论的碰撞检测是基于portal-based 及BSP-based 两种类型的引擎。因为每个引擎都有自己组织结构,这使得虚拟世界物体的碰撞检测技术也不尽相同。面向对象的碰撞检测是使用得比较多的,但这取决于你的现实可实性,就想将引擎分成两部分一样。稍后,我们会概述多边形碰撞检测,也会研究如何扩展我们的弯曲物体。
    This article will assume a basic understanding of the geometry and math involved in collision detection. At the end of the article, I’ll provide some references in case you feel a bit rusty in this area. I’ll also assume that you’ve read Jeff Lander’s Graphic Content columns on collision detection (“Crashing into the New Year,” ; “When Two Hearts Collide,”; and “Collision Response: Bouncy, Trouncy, Fun,” ). I’ll take a top-down approach to collision detection by first looking at the whole picture and then quickly inspecting the core routines. I’ll discuss collision detection for two types of graphics engines: portal-based and BSP-based engines. Because the geometry in each engine is organized very differently from the other, the techniques for world-object collision detection are very different. The object-object collision detection, for the most part, will be the same for both types of engines, depending upon your current implementation. After we cover polygonal collision detection, we’ll examine how to extend what we’ve learned to curved objects.

    / 3 …………………………………………………………………………………………………
    重要的图片
    编写一个最好的碰撞检测例程。我们开始设计并且编写它的基本程序框架,与此同时我们也正在开发着一款游戏的图形管线。要想在工程结束的时候才加入碰撞检测是比较不好的。因为,快速的编写一个碰撞检测会使得游戏开发周期延迟甚至会导致游戏难产。在一个完美的游戏引擎中,碰撞检测应该是精确、有效、而且速度要快。这些意味着碰撞检测必须通过场景几何学的管理途径。蛮力方法是不会工作的 — 因为今天,3D游戏每幀运行时处理的数据量是令人难以置信的。你能想象一个多边形物体的检测时间。
    在一个完美的比赛发动机,碰撞察觉应该是精确,有效,并且很快的。这些要求意味着那碰撞察觉必须仔细到景色被系住几何学管理管道。禽兽力量方法嬴得’t 工作—今天’s 3D 比赛每框架处理的数据的数量能是介意犹豫。去是你能核对对在景色的每另外的多角形的一个物体的每多角形的时间。
    The Big Picture
    To create an optimal collision detection routine, we have to start planning and creating its basic framework at the same time that we’re developing a game’s graphics pipeline. Adding collision detection near the end of a project is very difficult. Building a quick collision detection hack near the end of a development cycle will probably ruin the whole game because it’ll be impossible to make it efficient. In a perfect game engine, collision detection should be precise, efficient, and very fast. These requirements mean that collision detection has to be tied closely to the scene geometry management pipeline. Brute force methods won’t work — the amount of data that today’s 3D games handle per frame can be mind-boggling. Gone are the times when you could check each polygon of an object against every other polygon in the scene.

    / 4 …………………………………………………………………………………………………
    让我们来看看一个游戏的基本循环引擎。(Listing 1)
    http://www.gamasutra.com/features/20000330/bobic_l1.htm
    这段代码简要的阐明了我们碰撞检测的想法。我们假设碰撞没发生并且更新物体的位置,如果我们发现碰撞发生了,我们移动物体回来并且不允许它通过边界(或删除它或采取一些另外预防措施)。然而,因为我们不知道物体的先前的位置是否仍然是可得到的,这个假设是太过分简单化的。你必须为这种情况设计一个解决方案(否则,你将可能经历碰撞而你将被粘住)。如果你是一个细心的玩家,你可能在游戏中会注意到,当你走近一面墙并且试图通过它时,你会看见墙开始动摇。你正在经历的,是感动运动返回来的效果。动摇是一个粗糙的时间坡度的结果(时间片)。
    Let’s begin by taking a look at a basic game engine loop (Listing 1). A quick scan of this code reveals our strategy for collision detection. We assume that collision has not occurred and update the object’s position. If we find that a collision has occurred, we move the object back and do not allow it to pass the boundary (or destroy it or take some other preventative measure). However, this assumption is too simplistic because we don’t know if the object’s previous position is still available. You’ll have to devise a scheme for what to do in this case (otherwise, you’ll probably experience a crash or you’ll be stuck). If you’re an avid game player, you’ve probably noticed that in some games, the view starts to shake when you approach a wall and try to go through it. What you’re experiencing is the effect of moving the player back. Shaking is the result of a coarse time gradient (time slice).

    / 5 …………………………………………………………………………………………………
    但是我们的方法是有缺陷的。我们忘记在我们的方程中加入时间。图1显示了时间的重要性,因而它不能省去。就算一个物体不在时间 t1 或 t2 抵触,它可以在时间t1 < t < t2穿过t边界哪儿。这是非常正确的,我们已经有大而连续的框架可操作。我们会发现必须还要一个好方法来处理差异。
    But our method is flawed. We forgot to include the time in our equation. Figure 1 shows that time is just too important to leave out. Even if an object doesn’t collide at time t1 or t2, it may cross the boundary at time t where t1 < t < t2. This is especially true when we have large jumps between successive frames (such as when the user hit an afterburner or something like that). We&#39;ll have to find a good way to deal with discrepancy as well.

    / 6 …………………………………………………………………………………………………
    我们应该将时间作为第4维也加入到所有的计算中去。这些使得计算变得很复杂,然而,我们只能舍弃它们。我们也可从原来的物体在时间 t1 和 t2 之间的占据,然后靠着墙测试结果(图 2 )。
    We could treat time as a fourth dimension and do all of our calculations in 4D. These calculations can get very complex, however, so we’ll stay away from them. We could also create a solid out of the space that the original object occupies between time t1 and t2 and then test the resulting solid against the wall (Figure 2).

    / 7 …………………………………………………………………………………………………
    一条简单的途径就是在 2 不同的时间在一个物体的地点附近创造凸壳。这条途径的效率很低并且毫无疑问它会降低你游戏的执行速度。如果不建立凸壳,我们可以在物体附近建立一个范围框。在我们熟悉几种技术后,我们要再次回到这个问题上。
    An easy approach is to create a convex hull around an object’s location at two different times. This approach is very inefficient and will definitely slow down your game. Instead of constructing a convex hull, we could construct a bounding box around the solid. We’ll come back to this problem once we get accustomed to several other techniques.

    / 8 …………………………………………………………………………………………………
    另外的途径,它是更容易的实现但是少些精确,是在正中央为交叉的一半和测试细分给的时间间隔。
    另外的途径,其是更容易的实现但是少些精确,是细分在为在midpoint 的交叉的一半和测试的给的时间间隔。这计算能递归地为每个结果的一半返回。这途径将比先前的方法更快,但是它不能保证精确检测所有碰撞的。
    Another approach, which is easier to implement but less accurate, is to subdivide the given time interval in half and test for intersection at the midpoint. This calculation can be done recursively for each resulting half, too. This approach will be faster than the previous methods, but it’s not guaranteed to catch all of the collisions.

    / 9 …………………………………………………………………………………………………
    另外的隐藏的问题是 collide_with_other_objects ()例程,它检查一个对象是否在场景内与任何另外的对象交叉。如果我们的场景有很多物体时,这例程会变得更重要。如果我们需要在场景对所有的别的对象检查,我们将粗略地做
    Another hidden problem is the collide_with_other_objects() routine, which checks whether an object intersects any other object in the scene. If we have a lot of objects in the scene, this routine can get very costly. If we have to check each object against all other objects in the scene, we’ll have to make roughly

    图三

    (N choose 2 )的比较。因此,我们将要完成的工作就是比较数字的关系N2 (or O(N2))。但是我们能避免施行 O ( N2 )在若干方法之一的对明智的比较。例如,我们能把我们的世界划分成是静止的物体( collidees )并且移动的物体( colliders )的初速度 v=0 。例如,在一个房间里的一面僵硬的墙是一碰撞面和向墙被扔的一个网球球是一碰撞对象。我们能建立一个二叉树(为每个组的一个)给这些对象,并且然后检查哪个对象确实有碰撞的机会。我们能甚至进一步限制我们的环境以便一些碰撞对象不会与我们没有在 2 颗子弹之间计算碰撞的对方发生抵触,例程。当我们继续前进,这个过程将变得更清楚,为现在,让我们就说它是可能的。(为了减少场景方面数量的另外的方法就是建立一个八叉树,这已经超出这篇文章的范围,但是你可以在文末参看我给你列出的参考文献)现在让看看基于portal-based引擎的碰撞检测。
    (N choose 2) comparisons. Thus, the number of comparisons that we’ll need to perform is of order N2 (or O(N2)). But we can avoid performing O(N2) pair-wise comparisons in one of several ways. For instance, we can divide our world into objects that are stationary (collidees) and objects that move (colliders) even with a v=0. For example, a rigid wall in a room is a collidee and a tennis ball thrown at the wall is a collider. We can build two spatial trees (one for each group) out of these objects, and then check which objects really have a chance of colliding. We can even restrict our environment further so that some colliders won’t collide with each other — we don’t have to compute collisions between two bullets, for example. This procedure will become more clear as we move on, for now, let’s just say that it’s possible. (Another method for reducing the number of pair-wise comparisons in a scene is to build an octree. This is beyond the scope of this article, but you can read more about octrees in Spatial Data Structures: Quadtree, Octrees and Other Hierarchical Methods, mentioned in the “For Further Info” section at the end of this article.) Now lets take a look at portal-based engines and see why they can be a pain in the neck when it comes to collision detection.

    IMG upload/forum/200562134942.gif[/IMG]
     
     

    ----------------------------------------------------------------------------
     
    关于SLG中人物可到达范围计算的想法


    下面的没有经过实践,因此很可能是错误的,觉得有用的初学朋友读一读吧:)
    希望高人指点一二 :)

    简介:
    在标准的SLG游戏中,当在一个人物处按下鼠标时,会以人物为中心,向四周生成一个菱形的可移动区范围,如下:

      0
    000
    00s00
    000
      0

    这个图形在刚开始学习PASCAL时就应该写过一个画图的程序(是否有人怀念?)。那个图形和SLG的扩展路径一样。

    一、如何生成路径:
    从人物所在的位置开始,向四周的四个方向扩展,之后的点再进行扩展。即从人物所在的位置从近到远进行扩展(类似广宽优先)。

    二、扩展时会遇到的问题:
    1、当扩展到一个点时,人物的移动力没有了。
    2、当扩展的时候遇到了一个障碍点。
    3、当扩展的时候这个结点出了地图。
    4、扩展的时候遇到了一个人物正好站在这个点(与2同?)。
    5、扩展的点已经被扩展过了。当扩展节点的时候,每个节点都是向四周扩展,因此会产生重复的节点。

    当遇到这些问题的时候,我们就不对这些节点处理了。在程序中使用ALLPATH[]数组记录下每一个等扩展的节点,不处理这些问题节点的意思就是不把它们加入到ALLPATH[]数组中。我们如何去扩展一个结点周围的四个结点,使用这个结点的坐标加上一个偏移量就可以了,方向如下:

      3
      0 2
      1

    偏移量定义如下:
    int offx[4] = { -1, 0, 1, 0 };
    int offy[4] = { 0, 1, 0, -1 };

    扩展一个节点的相邻的四个节点的坐标为:
    for(int i=0; i<4; i )
    {
        temp.x = temp1.x offx[i];
        temp.y = temp1.y offy[i];
    }

    三、关于地图的结构:
    1、地图的二维坐标,用于确定每个图块在地图中的位置。
    2、SLG中还要引入一个变量decrease表示人物经过这个图块后他的移动力的减少值。例如,一个人物现在的移动力为CurMP=5,与之相领的图块的decrease=2;这时,如果人物移动到这里,那它的移动力变成CurMP-decrease。
    3、Flag域:宽度优先中好像都有这个变量,有了它,每一个点保证只被扩展一次。防止一个点被扩展多次。(一个点只被扩展一次真的能得到正确的结果吗?)
    4、一个地图上的图块是否可以通过,我们使用了一个Block代表。1---不可以通过;0---可以通过。

    这样,我们可以定义一个简单的地图结构数组了:

    #define MAP_MAX_WIDTH 50
    #define MAP_MAX_HEIGHT 50
    typedef struct tagTILE{
        int x,y,decrease,flag,block;
    }TILE,*LPTILE;
    TILE pMap[MAP_MAX_WIDTH][MAP_MAX_HEIGHT];

    以上是顺序数组,是否使用动态的分配更好些?毕竟不能事先知道一个地图的宽、高。

    四、关于路径:
    SLG游戏中的扩展路径是一片区域(以人物为中心向四周扩展,当然,当人物移动时路径只有一个)。这些扩展的路径必须要存储起来,所有要有一个好的结构。我定义了一个结构,不是很好:

    typedef struct tagNODE{
        int x,y;   //扩展路径中的一个点在地图中的坐标。
        int curmp; //人物到了这个点以后的当前的移动力。
    }NODE,*LPNODE;

    上面的结构是定义扩展路径中的一个点的结构。扩展路径是点的集合,因此用如下的数组进行定义:

    NODE AllPath[PATH_MAX_LENGTH];

    其中的PATH_MAX_LENGTH代表扩展路径的点的个数,我们不知道这个扩展的路径中包含多少个点,因此定义一个大一点的数字使这个数组不会产生溢出:

    #define PATH_MAX_LENGTH 200

    上面的这个数组很有用处,以后的扩展就靠它来实现,它应该带有两个变量nodecount 代表当前的数组中有多少个点。当然,数组中的点分成两大部分,一部分是已经扩展的结点,存放在数组的前面;另一部分是等扩展的节点,放在数组的后面为什么会出现已扩展节点和待扩展节点?如下例子:

    当前的人物坐标为x,y;移动力为mp。将它存放到AllPath数组中,这时的起始节点为等扩展的节点。这时我们扩展它的四个方向,对于合法的节点(如没有出地图,也没有障碍......),我们将它们存放入AllPath数组中,这时的新加入的节点(起始节点的子节点)就是等扩展结点,而起始节点就成了已扩展节点了。下一次再扩展节点的时候,我们不能再扩展起始节点,因为它是已经扩展的节点了。我们只扩展那几个新加入的节点(待扩展节点),之后的情况以此类推。那么我们如何知道哪些是已经扩展的结点,哪些是等扩展的节点?我们使用另一个变量cutflag,在这个变量所代表的下标以前的结点是已扩展节点,在它及它之后是待扩展结点。

    五、下面是基本框架(只扩展一个人物的可达范围):

    int nodecount=0; //AllPath数组中的点的个数(包含待扩展节点和已经扩展的节点
    int cutflag=0; //用于划分已经扩展的节点和待扩展节点
    NODE temp; //路径中的一个点(临时)
    temp.x=pRole[cur]->x; //假设有一个关于人物的类,代表当前的人物
    temp.y=pRole[cur]->y;
    temp.curmp=pRole[cur]->MP; //人物的最大MP
    AllPath[nodecount ]=temp; //起始点入AllPath,此时的起始点为等扩展的节点

    while(curflag<nodecount) //数组中还有待扩展的节点
    {
        int n=nodecount; //记录下当前的数组节点的个数。
        for(int i=cutflag;i<nodecount;i ) //遍历待扩展节点
        {
            for(int j=0;j<4;j ) //向待扩展节点的四周各走一步
            {
                //取得相邻点的数据
                temp.x=AllPath[i].x offx[j];
                temp.y=AllPath[i].y offy[j];
                temp.curmp=AllPath[i].curmp-pMap[AllPath[i].x][AllPath[i].y].decrease;
    //以下为检测是否为问题点的过程,如果是问题点,不加入AllPath数组,继续处理其它的点
                if(pMap[temp.x][temp.y].block)
                    continue; //有障碍,处理下一个节点
                if(temp.curmp<0)
                    continue; //没有移动力了
                if(temp.x<0||temp.x>=MAP_MAX_WIDTH|| temp.y<0||temp.y>=MAP_MAX_HEIGHT)
                    continue; //出了地图的范围
                if(pMap[temp.x][temp.y].flag)
                    continue; //已经扩展了的结点
                //经过了上面几层的检测,没有问题的节点过滤出来,可以加入AllPath
                AllPath[nodecount]=temp;
            }
            pMap[AllPath[i].x][AllPath[i].y].flag=1; //将已经扩展的节点标记为已扩展节点
        }
        cutflag=n; //将已扩展节点和待扩展节点的分界线下标值移动到新的分界线
    }
    for(int i=0;i<nodecount;i )
        pMap[AllPath[i].x][AllPath[i].y].bFlag=0; //标记为已扩展节点的标记设回为待扩展节点。
     

    --------------------------------------------------------------------------------


     
    无限大地图的实现

    这已经不是什么新鲜的东西了,不过现在实在想不到什么好写,而且版面上又异常冷清,我再不说几句就想要倒闭了一样。只好暂且拿这个东西来凑数吧。
    无限大的地图,听上去非常吸引人。本来人生活的空间就是十分广阔的,人在这么广阔的空间里活动才有一种自由的感觉。游戏中的虚拟世界由于受到计算机存储空间的限制,要真实地反映这个无限的空间是不可能的。而对这个限制最大的,就是内存的容量了。所以在游戏的空间里,我们一般只能在一个狭小的范围里活动,在一般的RPG中,从一个场景走到另一个场景,即使两个地方是紧紧相连的,也要有一个场景的切换过程,一般的表现就是画面的淡入淡出。

    这样的场景切换给人一种不连续的感觉(我不知道可不可以把这种称作“蒙太奇”:o)),从城内走到城外还有情可缘,因为有道城墙嘛,但是两个地方明明没有界限,却偏偏在这一边看不到另外一边,就有点不现实了。当然这并不是毛病,一直以来的RPG都是遵循这个原则,我们(至少是我)已经习惯了这种走路的方式。我在这里说的仅仅是另外一种看起来更自然一点的走路方式,仅此而已。

    当然要把整个城市的地图一下子装进内存,现在的确是不现实的,每一次只能放一部分,那么应该怎么放才是我们要讨论的问题。

    我们在以前提到Tile方法构造地图时就谈到过Tile的好处之一就是节省内存,这里仍然可以借鉴Tile的思想。我们把整个大地图分成几块,把每一块称作一个区域,在同一时间里,内存中只保存相邻的四块区域。这里每个区域的划分都有一定的要求:每个区域大小应该相等这是一定的了,不然判断当前屏幕在哪个区域中就成了一个非常令人挠头的事;另外每个区域的大小都要大于屏幕的大小,也只有这样才能保证屏幕(就是图中那块半透明的蓝色矩形)在地图上荡来荡去的时候,最多同时只能覆盖四个区域(象左图中所表示的),内存里也只要保存四个区域就足够了;还有一点要注意的,就是地图上的建筑物(也包括树啦,大石头啦什么的)必须在一个区域内,这样也是为了画起来方便,当然墙壁——就是那种连续的围墙可以除外,因为墙壁本来就是一段一段拼起来的。

    我们在程序中可以设定4个指针来分别指向这4个区域,当每次主角移动时,就判断当前滚动的屏幕是否移出了这四个区域,如果移出了这四个区域,那么就废弃两个(或三个)已经在目前的四个相邻区域中被滚出去的区域(说得很别扭,各位见谅),读入两个(或三个)新滚进来的区域,并重新组织指针。这里并不涉及内存区域的拷贝。

    这样的区域划分方法刚好适合我们以前提到的Tile排列方法,只要每个区域横向Tile的个数是个偶数就行了,这样相邻的两个区域拼接起来刚好严丝合缝,而且每个区域块的结构完全一致,没有那些需要重复保存的Tile(这个我想我不需要再画图说明了,大家自己随便画个草图就看得出来了)。在文件中的保存方法就是按一个个区域分别保存,这样在读取区域数据时就可以直接作为一整块读入,也简化了程序。另外还有个细节就是,我们的整个地图可能不是一个规则的矩形,可能有些地方是无法达到的,如右图所示,背景是黑色的部分代表人物不能达到的地方。那么在整个地图中,这一部分区域(在图中蓝色的3号区域)就可以省略,表现在文件存储上就是实际上不存储这一部分区域,这样可以节省下不少存储空间。对于这种地图可以用一个稀疏矩阵来存储,大家也可以发挥自己的才智用其他对于编程来说更方便的形式来存储地图。 

    这就是对无限大地图实现的一种方法,欢迎大家提出更好的方法。也希望整个版面能够活跃一点。


    April 11

    Unicode编码和utf-8编码之间的对应关系表

    The table below summarizes the format of these different octet types.
       The letter x indicates bits available for encoding bits of the
       character number.

       Char. number range  |        UTF-8 octet sequence
          (hexadecimal)    |              (binary)
       --------------------+---------------------------------------------
       0000 0000-0000 007F | 0xxxxxxx
       0000 0080-0000 07FF | 110xxxxx 10xxxxxx
       0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx    //////A/////////
       0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    这是一个Unicode编码和utf-8编码之间的对应关系表。中文的Unicode编码范围在0000 0800-0000 FFFF 中。我在前面发的代码只作了这些转换
    April 09

    手机相关术语大全


     
    手机新词汇

    bluetooth:蓝牙技术(无线耳机接听)

    Wi-Fi:wireless Fidelity 无线保真(即“小灵通”所采用的技术)

    Hi-Fi: High Fidelity 高保真

    3-G:Generation Three 第三代

    PHS:Personal Handyphone System 个人手提移动电话系统

    Walkie-Talkie:步话机

    Gotone:全球通------这个应该太熟悉不过了吧

    GPS:Global Positioning System 全球定位系统

    Monternet:Mobile+Internet 移动梦网

    GPRS:General Packet Radio Service 通用分组无线业务--这个很重要哦,要掌握

    SMS:Short Message Service 短信服务---------最最流行的service

    MMS:Multi-media Messaging Service 多媒体信息服务

    SIM卡:Subscriber Identity Module 客户身份识别卡-------现在知道SIM的全称是什么了吧

    GSM:Global System For Mobile Communications 全球移动通信系统

    WAP:Wireless Application Protocol 无线应用协议(即使手机具有上网功能)

    PAS:Personal Access System 个人接入系统(如“小灵通”)

    CDMA:Code Division Multiple Access 码多分址-----------超级重点哦

    pre-paid Phone Card:储值卡
    Roaming:漫游
    Voice Prompt:语音提示
    WLANs:Wireless Local Area Networks 无线局域网
    DV:Digital Video 数码摄像机
    3-D:Three-Dimension 三维
    LCD:Liquid Crystal Display 液晶显示
     
     
     


     
     
    全面理解手机中的英文短语

    1、TACS TACS的英文全称是TotalAccessCommunicationsSystem,它是一种全入网通信系统技术。该技术按

    照英国标准而设计的模拟式移动电话系统,其频率范围为900MHz。

    2、NetDevice

      按字面意思它是“网络设备”或“网络装置”,但实际上它既不是指路由器也不指交换机,而是能与

    Internet实现联网的小型设备,不包括台式机和笔记本电脑。NetDevice主要包括掌上电脑、双向呼机、机顶

    盒、智能电话、汽车PC,以及专门收发E-mail的小型工具等。也有人把 NetDevice称作

    InformationAppliance(信息家电)。

    3、WCDMA

      WCDMA是WidebandCodeDivisionMultipleAccess的简称。这是第三代无线通信(3G)的一种标准,能够提

    供足够的带宽,使无线多媒体应用成为可能。

    4、DAMPS

      DAMPS的全称是DigitalAMPS,其中AMPS是一种高级移动电话服务技术,该技术为模拟蜂窝系统,使用

    800MHz频谱,在美国占主导地位。相对应地,DigitalAMPS代表的是数字化高级移动电话系统。这种数字网络

    解决方案基于美国的IS-136数字标准。在900?1800MHz 频谱内执行。

    5、CMTS

      CMTS代表的是CellularMobileTelephoneSystem,中文含义是- 蜂窝移动电话系统。该系统内的每一个

    地区都由一个基站覆盖。一个地区称为一个信元。信元内的每部电话机都通过基站实现通信。如果该部电话机

    进入另一个信元,呼叫就自动转移至新信元内的基站。

    6、UMTS

      UMTS代表的是UniversalMobileTelecommunicationsSystem,中文含义是通用移动电信系统,特指下一

    代蜂窝技术。受到欧洲电信标准协会保护的一批公司目前正在制订其标准。

    7、NMT450/NMT900

      NMT是NordicMobileTelephoneSystem的英文缩写,特指北欧移动电话系统技术。它是根据北欧标准而设

    立的模拟移动电话系统,其频谱范围为450和900MHz。

    8、PDC

      PDC的英文全称是PersonalDigitalCellular,代表的是个人数字蜂窝电话。按照日本标准建立的蜂窝移

    动电话系统,频率范围为800和1500MHz。
    (一) GSM

      GSM全名为:Global System for Mobile Communications,中文为全球移动通讯系统,俗称"全球通",

    由欧洲开发的数字移动电话网络标准,它的开发目的是让全球各地共同使用一个移动电话网络标准,让用户使

    用一部手机就能行遍全球。GSM系统包括 GSM 900:900MHz、GSM1800:1800MHz 及 GSM-1900、1900MHz等

    几个频段 。

      GSM系统有几项重要特点:防盗拷能力佳、网络容量大、手机号码资源丰富、通话清晰、稳定性强不易受

    干扰、信息灵敏、通话死角少、手机耗电量低。目前世界上主要的两大GSM系统为GSM 900及GSM1800,由于采

    用了不同频率,因此适用的手机也不尽相同。前者发展的时间较早,使用的国家较多,后者发展的时间较晚,

    使用的国家也较少。物理特性方面,前者频谱较低,波长较长,穿透力较差,但传送的距离较远,而手机发射

    功率较强,耗电量较大,因此待机时间较短;而后者的频谱较高,波长较短,穿透力佳,但传送的距离短,其

    手机的发射功率较小,待机时间则相应地较长。

      (二) GPRS

      GPRS是 General Packet Radio Service宽频移动数据(又名封包无线数据服务)的缩写,GPRS最大功

    能在于将以往环状(circuit)网络在架设新的核心网络设备后,转变为分封(packet)的网络,使用的是一

    种频道分享的概念。为了能深刻理解这个概念,我们不妨举一个形象的例子:使用环状网络时,一条公路只能

    提供两个人互相对话,但是在分封网络时,一条公路却可以同时提供给多个人对话,充分有效地利用了系统的

    容量。

      GPRS具有的优势包括: 改善无线电频道的使用现状。 提供低成本,品质稳定的服务给更多的客户。 快

    速的连接。 GSM及GPRS可以同时存在而互不干扰。 可与其他IP (互联网协议)相连接。

      (三)CDMA

      CDMA (Code Division Multiple Access) 又称码分多址,是在无线通讯上使用的技术,CDMA 允许所有

    的使用者同时使用全部频带,并且把其他使用者发出的讯号视为杂讯,完全不必考虑到讯号碰撞

    (collision) 的问题。
    全面理解手机中的英文短语

    1、TACS

    TACS的英文全称是TotalAccessCommunicationsSystem,它是一种全入网通信系统技术。该技术按照英国标

    准而设计的模拟式移动电话系统,其频率范围为900MHz。

    2、NetDevice

      按字面意思它是“网络设备”或“网络装置”,但实际上它既不是指路由器也不指交换机,而是能与

    Internet实现联网的小型设备,不包括台式机和笔记本电脑。NetDevice主要包括掌上电脑、双向呼机、机顶

    盒、智能电话、汽车PC,以及专门收发E-mail的小型工具等。也有人把NetDevice称作

    InformationAppliance(信息家电)。

    3、WCDMA

      WCDMA是WidebandCodeDivisionMultipleAccess的简称。这是第三代无线通信(3G)的一种标准,能够提

    供足够的带宽,使无线多媒体应用成为可能。

    4、DAMPS

      DAMPS的全称是DigitalAMPS,其中AMPS是一种高级移动电话服务技术,该技术为模拟蜂窝系统,使用

    800MHz频谱,在美国占主导地位。相对应地,DigitalAMPS代表的是数字化高级移动电话系统。这种数字网络

    解决方案基于美国的IS-136数字标准。在900?1800MHz频谱内执行。

    5、CMTS

      CMTS代表的是CellularMobileTelephoneSystem,中文含义是-蜂窝移动电话系统。该系统内的每一个地

    区都由一个基站覆盖。一个地区称为一个信元。信元内的每部电话机都通过基站实现通信。如果该部电话机进

    入另一个信元,呼叫就自动转移至新信元内的基站。

    6、UMTS

      UMTS代表的是UniversalMobileTelecommunicationsSystem,中文含义是通用移动电信系统,特指下一

    代蜂窝技术。受到欧洲电信标准协会保护的一批公司目前正在制订其标准。

    7、NMT450/NMT900

      NMT是NordicMobileTelephoneSystem的英文缩写,特指北欧移动电话系统技术。它是根据北欧标准而设

    立的模拟移动电话系统,其频谱范围为450和900MHz。

    8、PDC

      PDC的英文全称是PersonalDigitalCellular,代表的是个人数字蜂窝电话。按照日本标准建立的蜂窝移

    动电话系统,频率范围为800和1500MHz。
    (一) GSM

      GSM全名为:Global System for Mobile Communications,中文为全球移动通讯系统,俗称"全球通",

    由欧洲开发的数字移动电话网络标准,它的开发目的是让全球各地共同使用一个移动电话网络标准,让用户使

    用一部手机就能行遍全球。GSM系统包括 GSM 900:900MHz、GSM1800:1800MHz 及 GSM-1900、1900MHz等

    几个频段 。

      GSM系统有几项重要特点:防盗拷能力佳、网络容量大、手机号码资源丰富、通话清晰、稳定性强不易受

    干扰、信息灵敏、通话死角少、手机耗电量低。目前世界上主要的两大GSM系统为GSM 900及GSM1800,由于采

    用了不同频率,因此适用的手机也不尽相同。前者发展的时间较早,使用的国家较多,后者发展的时间较晚,

    使用的国家也较少。物理特性方面,前者频谱较低,波长较长,穿透力较差,但传送的距离较远,而手机发射

    功率较强,耗电量较大,因此待机时间较短;而后者的频谱较高,波长较短,穿透力佳,但传送的距离短,其

    手机的发射功率较小,待机时间则相应地较长。

      (二) GPRS

      GPRS是General Packet Radio Service宽频移动数据(又名封包无线数据服务)的缩写,GPRS最大功能

    在于将以往环状(circuit)网络在架设新的核心网络设备后,转变为分封(packet)的网络,使用的是一种

    频道分享的概念。为了能深刻理解这个概念,我们不妨举一个形象的例子:使用环状网络时,一条公路只能提

    供两个人互相对话,但是在分封网络时,一条公路却可以同时提供给多个人对话,充分有效地利用了系统的容

    量。

      GPRS具有的优势包括: 改善无线电频道的使用现状。 提供低成本,品质稳定的服务给更多的客户。 快

    速的连接。 GSM及GPRS可以同时存在而互不干扰。 可与其他IP (互联网协议)相连接。

      (三)CDMA

      CDMA (Code Division Multiple Access) 又称码分多址,是在无线通讯上使用的技术,CDMA 允许所有

    的使用者同时使用全部频带,并且把其他使用者发出的讯号视为杂讯,完全不必考虑到讯号碰撞

    (collision) 的问题。

      CDMA的优点包括: CDMA中所提供的语音编码技术,其通话品质比目前的GSM好,而且可以把用户对话时

    周围环境的噪音降低,使通话更为清晰。CDMA利用展频的通讯技术,因而可以减少手机之间的干扰,并且可以

    增加用户的容量,而且手机的功率还可以做的比较低,不但可以使使用时间更长,更重要的是可以降低电磁波

    辐射对人的伤害。 CDMA的带宽可以扩展较大,还可以传输影像呢,这是第三代手机为什么选用CDMA的原因。

    就安全性能而言,CDMA不但有良好的认证体制,更因为其传输的特性,用分码多工,防止被人盗听的能力大大

    地增强。

      目前CDMA系统正快速发展中。 Wideband CDMA(WCDMA)宽带分码多工传输技术,为IMT-2000的重要基础

    技术,将是第三代数字无线通信系统的标准。

      (四)WAP

      WAP (Wireless Application Protocol)无线应用协议是一个开放式的标准协议,可以把网络上的信息

    传送到移动电话或其它无线通讯终端上。WAP是由爱立信(Ericsson)、诺基亚(Nokia)、摩托罗拉(Motorola)

    等通信业巨头在1997年成立的无线应用协议论坛(WAP Forum)中所制定的。它使用一种类似于HTML的标记式语

    言WML(Wireless Markup Language),并可通过WAP Gateway直接访问一般的网页。通过WAP,用户可以随时

    随地利用无线通讯终端来获取互联网上的即时信息或公司网站的资料,真正实现无线上网。

      (五)PHS

      PHS中文名为低功率移动电话。英文名全称为Personal Handy-phone System。PHS系统是日本自行研发

    的数字式无线电话系统。其发射功率远低于一般的GSM移动电话,所以它是唯一可在医院使用的移动通讯系统

    。PHS最适用于频密的闹市区,可提供与GSM系统同样的功能。其64K(预计明年可达128K)的传输速率更是GSM

    系统望尘莫及的。 PHS能支持无线多媒体通信(Wireless Multimedia Communication),它提供各种传输方

    式以使用户能够连上互联网,例如通过无线电传输、电话线路传输、光纤电缆传输等。因此用记能够以最适合

    自己的方式选择最佳的通信服务。 PHS系统可以提供完善的双向通信服务,例如提供手机用户的自动定位服务

    等。

      PHS的优点: 通话费低且具隐私性,在日本,PHS的通话费率仅比市话高出不到20%。手机待机时间和通

    话时间长,PHS手机市场上新出的款式通常"最低"待机时间都在300小时以上。高速数据传输能力,目前日本

    的通讯传输速率已经达到64kbps。 通话音质佳,PHS手机以接近市话的音质略胜GSM手机一筹。 手机发射功

    率较低,PHS手机的发射功率仅是GSM手机的六十分之一,即使长时间使用也不会有头痛、目眩等使用GSM手机

    的后的不适症状。而且可传音乐、图片及手绘图形。
    ■要CCD镜头和COMS镜头?
      严格的说CCD和COMS都是手机的数码相机模组中感光器件。其中CCD是电荷耦合组件的英文缩写,CMOS则

    是附加金属氧化物半导体组件的英文简称。两者在信息读取方式、速度、能耗和成像质量上都有所差别,相对

    而言,在手机这类简单的数码相机模块上感光器件采用CCD的从整体表现上来看是要优于COMS的,因此在同等

    情况下应该选择采用了CCD感光器件的照相手机。比如索爱最新的旗舰照相手机就是采用的CCD作为手机130万

    像素的感光器件。
    此外,感光器件的大小对成像质量的大小也起着决定性的影响,如诺基亚7650就采用了相对较大的感光器件因

    此拍摄的照片在同类手机中表现也更好。
    ■什么是VGA镜头?
      我们常常在关于新机的介绍中,看到类似“。。。。内置VGA镜头”的说法,那么什么是VGA镜头呢?其实

    VGA的英文全称是Video Graphic Array,即显示绘图阵列。在通常情况下,我们可以把VGA看作是640X480像

    素这种固定分辨率的英文缩写。如果一部手机上标明为VGA镜头则代表该机能够输入最大分辨率为640×480像

    素,而这个最大分辨率(640×480)的乘积为307200像素,就表明这摄像头的像素值为30万的了。也就是为

    什么有人也称30万像素镜头为VGA镜头的原因了。
    ■什么是3GPP格式?
      在目前上市的一些智能手机或者支持视频拍摄的手机中我们往往能看到所谓支持3GPP格式图象,那么什么

    是3GPP格式呢?简单的说,该格式是“第三代合作伙伴项目”(3GPP)制定的一种多媒体标准,使用户能使用

    手机享受高质量的视频、音频等多媒体内容。其核心由包括高级音频编码 (AAC)、自适应多速率 (AMR) 和

    MPEG-4 和 H.263 视频编码解码器等组成,目前大部分支持视频拍摄的手机都支持3GPP格式的视频播放。
    ■什么是MPEG4格式?什么是MotionJPEG格式?
      MPEG4超低码率运动图像和语言的压缩标准准。能够在带宽较小的情况下进行视频传输。而对于手机而言

    ,由于硬件限制,目前的照相手机一般只能拍摄低分辨率的MPEG4图象,如索爱K700C就支持128×96和176×

    144像素两种规格的视频图象。同样,当今大部分手机都支持下载和播放MPEG4格式的图象,即使手机本身不

    具备视频能力,如摩托罗拉C650等机型。
      MotionJPEG格式目前主要出现在三星、NEC等不具备长时间视频拍摄能力的手机上。它的主要特色是采用

    独特的失真压缩技术将影像数据中较不重要的部份去除,能有效减少视频文件大小,并将动画播放能力与JPEG

    相结合。有时候我们看到MJPEG其实就是MotionJPEG的缩写。如三星华盖系列的SCH X809以及SGH E800、NEC

    的N910以及阿尔卡特OT835等就支持该格式的视频。
    ■什么是QVGA屏幕
      QVGA屏幕是随着NEC N820和大唐GX20等手机开始出现在我们视野之中的,通俗的讲也可以说成是一种固

    定分辨率的英文缩写。QVGA即“QuarterVGA ”顾名思义就是说 VGA的4分之一尺寸。就是在液晶屏幕上输出

    的分辨率是240×320像素。需要说明的是有些媒体把QVGA屏幕当成与TFT和TFD等LCD材质相同的东西是错误的

    ,QVGA屏幕的说法多见与日本的一些手机中,目前采用微软PPC操作系统的智能手机屏幕也大多是320×240像

    素的QVGA屏幕。
    ■什么是SubQCIF格式?什么是QCIF格式?
      这两种视频规格最多的出现在诺基亚照相手机中,简单的说我们也可以把它们理解为一种固定分辨率的英

    文缩写,如SubQCIF则是128×96像素,而QCIF则对应的是176×144像素。此外,我们常见的CIF则是355×

    288像素、QQVGA则是160×120像素等。
      
    手机的的英文短语解释

    在目前上市的一些智能手机或者支持视频拍摄的手机中我们往往能看到所谓支持3GPP格式图象,那么什么是

    3GPP格式呢?简单的说,该格式是“第三代合作伙伴项目”(3GPP)制定的一种多媒体标准,使用户能使用手

    机享受高质量的视频、音频等多媒体内容。其核心由包括高级音频编码 (AAC)、自适应多速率 (AMR) 和

    MPEG-4 和 H.263 视频编码解码器等组成,目前大部分支持视频拍摄的手机都支持3GPP格式的视频播放。
    ■什么是MPEG4格式?什么是MotionJPEG格式?
      MPEG4超低码率运动图像和语言的压缩标准准。能够在带宽较小的情况下进行视频传输。而对于手机而言

    ,由于硬件限制,目前的照相手机一般只能拍摄低分辨率的MPEG4图象,如索爱K700C就支持128×96和176×

    144像素两种规格的视频图象。同样,当今大部分手机都支持下载和播放MPEG4格式的图象,即使手机本身不

    具备视频能力,如摩托罗拉C650等机型。
      MotionJPEG格式目前主要出现在三星、NEC等不具备长时间视频拍摄能力的手机上。它的主要特色是采用

    独特的失真压缩技术将影像数据中较不重要的部份去除,能有效减少视频文件大小,并将动画播放能力与JPEG

    相结合。有时候我们看到MJPEG其实就是MotionJPEG的缩写。如三星华盖系列的SCH X809以及SGH E800、NEC

    的N910以及阿尔卡特OT835等就支持该格式的视频。
    ■什么是QVGA屏幕
      QVGA屏幕是随着NEC N820和大唐GX20等手机开始出现在我们视野之中的,通俗的讲也可以说成是一种固

    定分辨率的英文缩写。QVGA即“QuarterVGA ”顾名思义就是说 VGA的4分之一尺寸。就是在液晶屏幕上输出

    的分辨率是240×320像素。需要说明的是有些媒体把QVGA屏幕当成与TFT和TFD等LCD材质相同的东西是错误的

    ,QVGA屏幕的说法多见与日本的一些手机中,目前采用微软PPC操作系统的智能手机屏幕也大多是320×240像

    素的QVGA屏幕。
    ■什么是SubQCIF格式?什么是QCIF格式?
      这两种视频规格最多的出现在诺基亚照相手机中,简单的说我们也可以把它们理解为一种固定分辨率的英

    文缩写,如SubQCIF则是128×96像素,而 QCIF则对应的是176×144像素。此外,我们常见的CIF则是355×

    288像素、QQVGA则是160×120像素等。
     
     
     
     
     

     

    本文涉及的名词

    1、1G/2G/2.5G/3G, GSM, GPRS, UTMS, CDMA.
    2、WAP and WML, i-Mode and CHTML.
    3、Bluetooth, Wireless LAN, HomeRF。
    4、SyncML, VoiceXML.

    -----------
    什么是1G/2G/2.5G/3G

    1G(first generation)表示第一代移动通讯技术。如现在以淘汰的模拟移动网。

    2G(second generation)表示第二代移动通讯技术。代表为GSM。以数字语音传输技术为核心。

    2.5G是基于2G与3G之间的过渡类型。代表为GPRS。比2G在速度、带宽上有所提高。可使现有GSM网络轻易地实

    现与高速数据分组的简便接入。

    3G(third generation)表示第三代移动通讯技术。面向高速、宽带数据传输。


    国际电信联盟(ITU)称其为IMT-2000(International Mobile Telecom-munication)。最高可提供

    2Mbp/s的数据传输速率。主流技术为CDMA技术代表有WCDMA(欧,日)、CDMA2000(美)和TD-SCDMA(中)

    -----------
    什么是GSM

    全球移动通讯系统(Global system for Mobile communications)的英文缩写。2G的主流技术,数据速率

    为9.6kb/s。

    -----------
    什么是GPRS

    通用分组无线业务(General Packet Radio Service)的英文缩写。是一种基于GSM系统的无线分组交换技

    术。是2.5G的主流技术。理论最高数据速率为171.2kb/s 。


    -----------
    什么是UMTS

    UMTS(Universal Mobile Telecommunication System)通用移动通信系统的英文缩写。由欧洲电信标准协

    会(ETSI)负责UMTS的标准化工作。并与ITU负责的IMT-2000协调一致。它是ITU IMT-2000的重要组成部分

    。UMTS使用ITU分配的、用于陆地和卫星无线通信的频带。它可通过移动或固定、公用或专用网络接入,与

    GSM和IP兼容。可支持2Mb/s的数据速率。


    -----------
    什么是CDMA(注:这里指3G的CDMA)

    码分多址的英文缩写,是目前公认的3G主流技术。

    目前存在3种3G的主流CDMA标准,分别是WCDMA、CDMA2000和TD-SCDMA。前两者分别由欧洲和美国提出,TD-

    SCDMA由中国提出(大唐电信),已被ITU和3GPP所接受。其中,WCDMA和CDMA2000是FDD模式,而TD-SCDMA

    是TDD模式(注:FDD-频分双工,需用两个频段进行收发;TDD-时分双工,采用同一个频段,但以不同的时

    隙进行。)

    -----------
    WAP和WML

    WAP是无线应用协议(Wireless Application Protocal)的英文缩写。它是无线互联网上的一系列协议的组

    合。面向移动电话等小型、窄带的移动设备。WAP能够运行于各种无线网络之上,如GSM、GPRS、CDMA等。WML

    是无线注标语言(Wireless Makeup language)的英文缩写。支持WAP技术的手机能浏览由WML描述的

    Internet内容。

    -----------
    I-mode 和 CHTML

    i-mode是日本电信(NTT)的子公司DoCoMo在日本市场推出的无线通讯服务。是目前世界上使用人数最多(都

    在日本)的无线互联网服务。I-mode 和 WAP 的主要区别在于:I-mode 的内容是用CHTML写成的,因此现行

    的大部分网络内容只要稍做修改可以使用;而WAP使用的是WML,现有的网络内容必须转化为WML才能被WAP所

    使用。

    CHTML(Compact HTML)HTML的一种变体。与HTML大部分兼容。

    (注:建议大家去www.nttdocomo.com看看,很Cool。)

    -----------
    蓝牙(BlueTooth)

    蓝牙是一种支持设备短距离通信(一般是10m之内)的无线电技术。能在包括移动电话、PDA、无线耳机、笔记

    本电脑、相关外设等众多设备之间进行无线信息交换。它的标准是IEEE802.15。工作在 2.4HGz 频带。带宽

    为1Mb/s
    (注:蓝牙这名字很有意思,来自公元10世纪统一丹麦和瑞典的斯堪的纳维亚国王的名字。)

    -----------
    Wireless LAN

    无线局域网,是由局域网发展而来,标准是IEEE802.11、IEEE802.11b 和IEEE802.11a。其中802.11b 工作

    在2.4GHz频带,带宽可达11Mbps。而802.11a定义在5GHz频带,带宽有望达到54Mb/s 。但相应地,Wireless

    LAN成本较高,使用昂贵。

    -----------
    HomeRF

    HomeRF主要为家庭网络设计的无线射频技术,是IEEE802.11与DECT的结合,旨在降低成本。HomeRF也采用了

    扩频技术,工作在2.4GHz频带,目前HomeRF的带宽为1~2Mb/s,未来会增到10Mb/s。


    -----------
    SyncML

    SyncML是一种行业通用的移动数据同步化协议。利用SyncML可使移动设备上的数据与远程数据保持同步状态

    。由Ericsson、 IBM、 Lotus、 Matsushita、Motorola、 Nokia、 Palm、 Psion和Starfish Software

    等公司组成的协会所开发。


    -----------
    VoiceXML

    VoiceXML(Voice eXtensible Markup Language)是W3C定义的可扩展标记语言(XML)的一种扩展,根据播

    放的提示信息、口述的命令、语音或按键音输入,实现人机交互。VoiceXML的标准化将简化Web上具有语音响

    应服务的个性化界面的创建,使人们能够通过语音和电话访问网站上的信息和服务。

    -----------------
    UMTS

    (Universal Mobile Telecommunications System)通用无线通信系统的英文缩写。是ITU IMT-2000的组成

    部分之一。UMTS使用ITU分配的、用于陆地和卫星无线通信的频带。它可通过移动或固定、公用或专用网络接

    入,与GSM和IP兼容。支持2Mb/s的数据速率。未来能达到更高。

    -----------------
    iDEN

    (The Integrated Digital Enhanced Network)集成数字增强型网络。 是摩托罗拉开发的数字集群无线网

    络系统。目前世界上最大的iDEN网由美国的Nextel运营。

    ------------------
    cdmaOne
    IS-95 CDMA的商标名。

    -----------------
    PHS和PDC

    PHS(Personal Handyphone System )个人手持系统,
    PDC(Personal Digital Cellular) 个人数字蜂窝

    PHS和PDC都是日本专用的移动通讯系统

    ---------------
    i-appli

    也称为“java for i-mode",i-appli 是NTT DoCoMo 专有的J2ME-cldc应用程序,

    也就是NTT DoCoMo版的MIDlet。

     


    手机专业术语名词解释
    当今是通讯技术迅速发展的社会,专业术语层出不穷。下面让大家了解以上的专业术语所指为何。
    CDMA

    CDMA是Code-Division Multiple Access的缩写,全称码分多址,是最近才被应用于商业的一种数字接口技

    术。它拥有频率利用率较高、手机功耗低等优点。中国联通推出的CDMA属于2.5代技术。目前第三代CDMA的标

    准有WCDMA、CDMA2000和TD-SCDMA等。
    W—CDMA

    即WidebandCDMA,也称为CDMADirectSpread,意为宽频分码多重存取,其支持者主要是以GSM系统为主的欧

    洲厂商,日本公司也或多或少参与其中,包括欧美的爱立信、阿尔卡特、诺基亚、朗讯、北电,以及日本的

    NTT、富士通、夏普等厂商。这套系统能够架设在现有的GSM网络上,对于系统提供商而言可以较轻易地过渡,

    而GSM系统相当普及的亚洲对这套新技术的接受度预料会相当高。因此W—CDMA具有先天的市场优势。

    CDMA2000也称为IMT-CDMA Multi-Carrier or IS-136
    由美国高通北美公司为主导提出,摩托罗拉、Lucent和后来加入的韩国三星都有参与,韩国现在成为该标准的

    主导者。这套系统是从窄频CDMA One数字标准衍生出来的,可以从原有的CDMA One结构直接升级到3G,建

    设成本低廉。但目前使用CDMA的地区只有日、韩和北美,所以CDMA2000的支持者不如W—CDMA多。不过

    CDMA2000的研发技术却是目前各标准中进度最快的,许多3G手机已经率先面世。
    TD—SCDMA

    该标准是由中国大陆独自制定的3G标准,1999年6月29日,中国原邮电部电信科学技术研究院(大唐电信)向

    ITU提出。该标准将智能无线、同步CDMA和软件无线电等当今国际领先技术融于其中,在频谱利用率、对业务

    支持具有灵活性、频率灵活性及成本等方面的独特优势。另外,由于中国内的庞大的市场,该标准受到各大主

    要电信设备厂商的重视,全球一半以上的设备厂商都宣布可以支持TD—SCDMA标准。
    GPRS

    随时上网的GPRS:GPRS(General Packet Radio Service)的中文含义为整合封包无线服务,它是利用而“

    分封交换”(Packet-Switched)的概念所发展出的一套无线传输方式,是在现有的GSM系统上发展出来的一

    种新的分组数据承载业务,我们可以将GPRS理解为GSM的一个更高层次。所谓的分封交换就是将数据分装成许

    多独立的封包,再将这些封包一个一个传送出去,形式上有点像寄包裹,采用分封交换的好处是只有在有资料

    需要传送时才会占用频宽,而且可以以传输的资料量计价,这对用户来说是比较合理的计费方式。

    GSM

    GSM是Global System for Mobile Communications的缩写,意为全球移动通信系统,是全球最成熟的数字移

    动电话网络标准之一,目前世界上大概有75%的手机使用的标准是GSM。截止到2001年,全世界162个国家已

    经建设了400个GSM通信网络。
    2.5G

    目前已经进行商业应用的2.5G移动通信技术是从2G迈向3G的衔接性技术,由于3G是个相当浩大的工程,所牵

    扯的层面多且复杂,要从目前的2G迈向3G不可能一下就衔接得上,因此出现了介于2G和3G之间的2.5G。HSCSD

    、WAP、EDGE、蓝芽(Bluetooth)、EPOC等技术都是2.5G技术。
    HSCSD

    HSCSD(高速电路交换数据服务)这是GSM网络的升级版本,HSCSD(High Speed Circuit Switched 

    Data)能够透过多重时分同时进行传输,而不是只有单一时分而已,因此能够将传输速度大幅提升到平常的二

    至三倍。目前新加坡M1与新加坡电讯的移动电话都采用HSCSD系统,其传输速度能够达到57.6kbps。
    WAP(无线应用通讯协议)

    WAP(Wireless Application Protocol)是移动通信与互联网结合的第一阶段性产物。这项技术让使用者

    可以用手机之类的无线装置上网,透过小型屏幕遨游在各个网站之间。而这些网站也必须以WML(无线标记语

    言)编写,相当于国际互联网上的HTML(超文件标记语言)。
    EDGE

    EDGE的英文全称为Enhanced Data rate for GSM Evolution,中文含义为改进数据率GSM服务,该技术主要

    在于能够使用宽带服务,能够让使用800、900、1800、1900MHz频段的网络提供第三代移动通信网络的部分功

    能,并且能大大改进目前在GSM和TDMA/136上提供的标准化服务。该技术可以提供384kbps的广域数据通信服

    务和大约2Mbps的局域数据通信服务,这样可以充分满足未来无线多媒体应用的带宽需求。
    蓝芽(Bluetooth)

    蓝牙是一种短距的无线通讯技术,电子装置彼此可以透过蓝牙而连接起来,传统的电线在这里就毫无用武之地

    了。透过芯片上的无线接收器,配有蓝牙技术的电子产品能够在十公尺的距离内彼此相通,传输速度可以达到

    每秒钟1兆字节。以往红外线接口的传输技术需要电子装置在视线之内的距离,而现在有了蓝牙技术,这样的

    麻烦也可以免除了。
    3G

    3G是英文3rd Generation的缩写,指第三代移动通信技术。相对第一代模拟制式手机(1G)和第二代GSM、

    TDMA等数字手机(2G),第三代手机一般地讲,是指将无线通信与国际互联网等多媒体通信结合的新一代移动

    通信系统。它能够处理图像、音乐、视频流等多种媒体形式,提供包括网页浏览、电话会议、电子商务等多种

    信息服务。为了提供这种服务,无线网络必须能够支持不同的数据传输速度,也就是说在室内、室外和行车的

    环境中能够分别支持至少2Mbps(兆字节/每秒)、384kbps(千字节/每秒)以及144kbps的传输速度。
    MMS

    MMS是Multimedia Message Service的简称,中文名为多媒体信息服务。MMS的工业标准是由两个组织,WAP

    Forum(WAP论坛)和3GPP(3G Partnership Project:3G伙伴计划)所制订的。因此,MMS是设计成可以在

    WAP协议的上层运行,它不局限于传输格式,既支持电路交换数据格式(circuit-switched data),也支持

    通用分组无线服务GPRS格式(general packet radio service)。其工作原理为利用高速传输技术EDGE

    (Enhanced Data rates for GSM Erolution是一种提高数据速率的新技术,是GSM向第三代移动通信系统

    IMT-2000过渡的台阶。它也被称为"GSM 384",因为这种技术能使数据速率由目前的9.6kbit/s提高到

    384kbit/s,这种速率可以支持语音、因特网浏览、电子邮件、会议电视等多种高速数据业务)和GPRS的支持

    下,以WAP(无线应用协议)为载体传送视频、图片、声音和文字。
    EMS

    EMS是英文Enhanced Message Service的缩写,中文意为增强型短消息服务。它比起SMS来,EMS的优势是除

    了可以像SMS那样发送文本短消息之外,还可以发送简单的图像、声音和动画等信息。而它最大的优势是仍然

    可以运行在原有SMS运行的GSM网络上,并且在发送途径和操作方法上也没有差别。
    小灵通

    小灵通又名无线市话PAS(Personal Access Phone System),是一种新型的个人无线接入系统,它采用先进

    的PHS微蜂窝技术,将市话传输交换与无线接入技术有机结合在一起,利用市话的交换传输资源,以无线方式提

    供给一定范围内具备移动漫游性能的个人通信终端.简言之,“小灵通”就是通过一定的技术手段,将原来只

    能固定使用的电话改变成为随身携带和移动使用的无线电话。
    3C产品

    所谓“3C产品”,就是计算机(Computer)、通信(Communication)和消费类电子产品

    (ConsumerElectronics)三者结合,亦称“信息家电”。由于3C产品的体积一般都不大,所以往往在中间加

    一个“小”字,故往往统称为“3C小家电”.
    3C认证

    根据中国入世承诺和体现国民待遇的原则,国家对强制性产品认证使用统一的标志。新的国家强制性认证标志

    名称为"中国强制认证",英文名称为"China Compulsory Certification",英文缩写为"CCC"。中国强制认

    证标志实施以后,将逐步取代原来实行的"长城"标志和"CCIB"标志。
    GSM/CDMA双模机

    所谓的“GSM/CDMA双模手机”就是指手机可以同时支持GSM以及CDMA这两个网络通信技术,它可以根据环境或

    者是实际操作的需要来从中做出选择,哪个网络技术更能发挥作用,就让手机切换到哪种模式下去工作,如果

    在一种模式下,手机通信质量不高或者是出现其他不良的通信现象,可以自由转到另外一个网络模式上工作,

    它实际上就是扩大了手机的通话频率,并大大提高通信的稳定性而已。
    分辨率

    分辨率(RESOLUTION)是指LCD显示器所能表示的像素个数。像素越密,分辨率越高,图像越清晰。液晶显示

    器的分辨率取决于显示器中液晶点数量。例如,蒙宝欧320手机待机图片像素为128?80(宽?高,单位:点)

    128?80代表的就是显示器的水平线和垂直线上的像素Pixel有多少。128即表明该显示器每行水平线上最多能

    表现128个像素Pixel。而垂直的一共有80行,那么128?80=10240个象素。
    65536颜色(灰度级)

    所谓颜色或灰度级指黑白显示器中显示像素点的亮暗差别,在彩色显示器中表现为颜色的不同,灰度级越多,

    图像层次越清楚逼真。灰度级取决于每个像素对应的刷新存储单元的位数和显示器本身的性能。如每个象素的

    颜色用16位二进制数表示,我们就叫它16位图,它可以表达2的16次方即65536种颜色。如每一个象素采用24

    位二进制数表示,我们就叫它24位图,它可以表达2的24次方即16777216种颜色。
    JAVA

    Java是由Sun微系统公司所发展出来的程序语言,中文译名为爪哇,它本身是一种对象导向(Object-

    Oriented)的程序语言,所以在使用学习上并不会很困难,如果您有使用过C++语言的话,那么写Java就更能

    驾轻就熟了,因为基本上 Java 的使用是比 C++ 还要简单一些。
    Java也号称是能跨平台使用的语言,这主要是因为Java本身被编译之后,并不是直 接产生可执行的码,而是

    产生一种中间码叫作 ByteCode,这种码必需在透过 Java 的直译 器来解读它,才能够真正的被执行,所以

    只要平台上装有这种Java的直译器,就能解读 ByteCode也就能执行Java编译过的程序,故与Java程序是在那

    种平台上被编译的,就完全没有干系了。Java写出来的程序可分为两类,分别是Java Applet与一般的

    Application,而Application 这一类就与一般的程序如C++的作用是比较类似的,反正就是一个独立可执行

    的应用程序,像HotJava是一个浏览器,且就是使用Java程序所发展出来的。最常见的Java程序包括应用程序

    和applets。应用程序是单独的程序,诸如HotJava浏览器软件就是用Java语言编写的。 Applets类似于应用

    程序,但是它们不能单独运行, Applets可以在支持Java的浏览器中运行。Applets主要是内置于HTML网页中

    ,在浏览时发挥作用。  Java是一个由Sun公司所开发出来的新一代程序语言。Java的目标是为

    了满足在一个充满各式各样不同种机器,不同操作系统平台的网络环境中开发软件。利用Java程序语言,

    你可以在你的网页中加入各式各样的动态效果。你可以放上一段动画,你可以加入声音,你也可以建立交互式

    网页,如果你愿意,就像一个窗口程序一样,你能加上菜单和按钮以及卷动轴。没有什么是做不到的,只要是

    Java!仔细想想,每次去添购高级的设备,只是为了装一些非常少用到的程序?而每一次使用新软件,我

    都要安装一次,而安装软件并不是不会遇到问题,对一般使用电脑的人来说还能解决,但是对完全没有碰过电

    脑的人来说,这可不是一件轻松的事。由于Internet的流行Java的出现,这样的一种僵局,是很

    有可能被打破的。姑且不论将来软件界会不会以上面预期的方式来经营,但几年之后软件界肯定和现今会有很

    大的差异,因为在Internet和Java下,什么事都可能发生。
    LAS-CDMA

    LAS-CDMA技术是由中国方正连宇通信公司提出,同属于3G技术标准,LAS-CDMA(大区域同步码分多址联接)

    技术的特点在于使用了一种被称为LAS编码的创新性的扩频编码设计,是一项具有跨越性的创新技术。它革命

    性地改变了传统CDMA的技术发展路线,通过减少系统产生的干扰来增加系统容量。LAS编码由被称为LA码和LS

    码的两级编码组成。尤其是LAS-CDMA能加强现在所有3G技术,把它们的频谱效率至少提高3倍。 LAS-CDMA即

    TD-LAS技术,可以完全克服传统TDD技术所存在的严重缺陷,这使得LAS-CDMA具有向新一代全IP移动通信技术

    延伸发展的巨大潜力。
    BREW

    BREW是Binary Runtime Enviroment for Wireless的缩写,意思为“无线应用下载”。使用具有BREW功能

    的CDMA手机,可以从数个无线数据应用类别中选择他们喜爱的应用,这些应用包括游戏和娱乐、商业应用和导

    航业务、天气和新闻、聊天和电子商务等。BREW 平台是一个无线手持设备的标准应用程序开发环境,手持设

    备涵盖范围从便宜的大众化电话到多功能高端无线设备。通过该平台,您可以编写能在多种电话上使用的应用

    程序,而不要求对每个新的电话型号进行应用程序修改。BREW 解决了当前的编程难题,如不需要电话及其软

    件的内部知识。
    J2ME
    KJava:KJava即J2ME(Java 2 Micro Edition),是Sun公司专门用于嵌入式设备的Java软件。以KJava编

    程语言为手机开发应用程序,可以提供游戏、个人信息处理、股票、电子地图等服务程序。J2ME(Java 2

    Micro Edition)是致力于消费产品和嵌入式设备的最佳解决方案. J2ME在设计其规格的时候,遵循着「对于

    各种不同的装置而造出一个单一的开发系统是没有意义的事」这个基本原则。于是J2ME先将所有的嵌入式装置

    大体上区分为两种:一种是运算功能有限、电力供应也有限的嵌入式装置(比方说PDA、手机);另外一种是运算

    能力相对较佳、并请在电力供应上相对比较充足的嵌入式装置(比方说冷气机、电冰箱、电视机上盒(set-top

    box))。因为这两种区分,所以Java引入了一个叫做Configuration的概念,然后把上述运算功能有限、电力

    有限的嵌入式装置定义在Connected Limited Device Configuration(CLDC)规格之中;而另外一种装置则规

    范为Connected Device Configuration(CDC)规格。也就是说,J2ME先把所有的嵌入式装置利用

    Configuration的概念区隔成两种抽象的型态。
    DS-CDMA

    DS-CDMA技术遵循ITU规定的IMT-2000规格,并以W-CDMA方式为基础的一种通信技术。该技术能够利用5MHz的

    信道提供高达2Mbps的数据速度,同时能够扩大系统容量,提高通话时的语音质量,降低通话的掉线率,支持

    IP数据服务。DS-CDMA技术除了能提供窄带业务(如话音业务)之外,还能提供多种用户速率通信、VOD带宽的

    能力,以及根据不同业务提供不同服务等级的能力。在CDMA标准中,DS-CDMA技术是其中的重要部分,是实现

    无线多媒体通信的关键。DS-CDMA技术最早起源于欧洲和日本的第三代无线研究活动,GSM的巨大成功对第三

    代系统在欧洲的标准化产生重大影响。在1996年,日本推出了一套DS-CDMA的实验系统方案,并得到了当时世

    界上主要的移动设备制造商的支持。1998年12月成立的3GPP(第三代伙伴项目)极大地推动了DS-CDMA技术的

    发展,加快了DS-CDMA的标准化进程,并最终使DS-CDMA技术成为ITU批准的国际通信标准。  DS-CDMA基于

    ANSI-41核心网,它使用新的频带,采用FDD工作方式,码片速率为3.84Mbps。DS-CDMA有更大的覆盖范围,采

    用自适应天线及多用户检测等新技术,并可支持频率间切换。由DS-CDMA技术组成的通信系统通常包括无线基

    地局装置、无线网络控制装置、多媒体信号处理装置。DS-CDMA系统的空中连接采用5MHz、10MHz或20MHz的无

    线信道
    TFT

    TFT(Thin Film Transistor)即薄膜场效应晶体管。
    所谓薄膜晶体管,是指液晶显示器上的每一液晶象素点都是由集成在其后的薄膜晶体管来驱动。从而可以做到

    高速度、高亮度、高对比度显示屏幕信息。TFT属于有源矩阵液晶显示器TFT-LCD液晶显示屏是薄膜晶体管型

    液晶显示屏,也就是“真彩”(TFT)。 TFT液晶为每个像素都设有一个半导体开关,每个像素都可以通过点

    脉冲直接控制,因而每个节点都相对独立,并可以连续控制,不仅提高了显示屏的反应速度,同时可以精确控

    制显示色阶,所以TFT液晶的色彩更真。 TFT液晶显示屏的特点是亮度好、对比度高、层次感强、颜色鲜艳,

    但也存在着比较耗电和成本较高的不足。TFT液晶技术加快了手机彩屏的发展。新一代的彩屏手机中很多都支

    持65536色显示,有的甚至支持16万色显示,这时TFT的高对比度,色彩丰富的优势就非常重要了。 TFT型的

    液晶显示器主要的构成包括:萤光管、导光板、偏光板、滤光板、玻璃基板、配向膜、液晶材料、薄模式晶体

     

    手机密码普级知识
    1. 手机密码
      手机密码是用以防止手机被盗用,在“保密设定” -- “开机密码” -- “手机密码”开启此功能之后

    ,手机开机时需输入手机密码方可使用,即此密码是对手机本身的锁定。一般手机密码的默认值是 1234 或

    0000

    2.pin1 码
       pin1 码是由供应商提供,用于 Sim 卡保密的个人识别码( Personal Identification Number ) ,

    在“保密设定” -- “开机密码” -- “ pin ”开启此功能之后,手机开机时需输入 pin1 码方可使用,即

    此密码是对 Sim 卡的锁定。默认值是 1234 。如果手机密码和 pin1 码同时使用,则先输入 pin1 码,后输

    入手机密码。 pin1 码 3 次输入错误之后将被锁死,需用 puk1 来解锁。
       3.puk1 码
       puk1 码是由供应商提供的 pin1 码的解锁码,是一串无规律的数字。 puk1 十次输错, sim 卡将永久

    锁死,只得更换 sim 卡

       4.pin2 码
       pin2 码是由供应商提供的 sim 卡另一密码,用于限定拨号等功能的个人识别码,主要用于消除呼叫费

    用数据、设定通话费的计费币别和计费单位、费用限制功能、限定拨号(“保密设定” -- “限定拨号”中开

    启之后手机只能拨其中设定的号码且不可用电话簿)。我的手机的 sim 卡默认值是 2345 。 pin2 码 3 次

    输入错误之后将被锁死,需用 puk2 来解锁。
       5.puk2 码
       puk2 码是由供应商提供的 pin2 码的解锁码,是一串无规律的数字。 puk2 十次输错, sim 卡也将永

    久锁死,只得更换 sim 卡。
       注: pin1 、 pin2 、 puk1 、 puk2 码均可到供应商处查询,且 pin1 、 pin2 也可自己修改(须

    知原来的密码)。
       6.sim 卡解锁码
      主要用于“锁定 sim 卡”功能的解锁,为防止未知的 sim 卡未经允许使用本手机,可开启“锁定 sim

    卡”(“保密设定” -- “锁定 sim 卡”)功能。这样,如果手机中的 sim 卡未经允许,在开机时就要按

    照提示输入解锁码。默认值是 00000000 。

     

    数字手机的解锁,由于各型号手机所配装的用户识别智能卡(sim卡)中存有卡号、国际移动用户识别号、用

    户服务表、密钥、认证算法和防盗个人密码识别号pin(4-8位数字组成),为确保安全,使用手机时如连续

    三次输入错误的个人密码,sim卡便会立即自锁。各种数字手机的解锁码均为“1234”。若输入“1234”仍不

    能解锁,就不要乱动了,应到电信部门处理,以免继续输入误码烧坏手机。    
      另外,解锁时要注意,若启用了自动上锁功能(menu+b+m+),则每次开机都需解锁。想取消时可先输
    入解锁码,再同时按menu、b、g健。设置解锁码时不选取“999”,因为该号码是国外报警电话号码,即使手

    机自锁,“999”电话仍能拨通。
      
      1、卡锁住了怎么办?sim卡本身会有一组pin码,用来保护手机用户门号不易遭盗用,所以一但启用pin码

    后,手机一开机便会要求输入四位数的pin码。不过要注意,pin码只有三次输入机会,错误三次后,sim卡就

    会锁住,无法使用。此时请联络移动公司服务电话,他们会告诉您另一组数字(puk码),来解开sim卡锁住。

    购卡时puk码会标示在大卡上。
      
      2、是sim卡?pin2?pin码?1.pin2是电信局用于计费的,一般不向用户提供,如果你的pin2或者pin码被

    锁了,可以到电信局免费开启。尽量不要乱按pin和pin2码!  2.sim卡就是你的手机卡,它记录你的号码

    、及电话簿,现在有三种sim卡,一种只能够存20个电话号码;一种能够存40个电话号码;最新的是叫stksim

    卡用于手机的信息服务如信息点播用,暂时仍然未流行,但将会成为趋热。  3.如果你对自己的sim卡存号

    码数不满意或sim坏了可以到电信局更换新卡。

     

    小灵通的基础知识
    一、从原理方面来讲:“小灵通手机信道是从251—255及1—82信道。频率是从1893.65 -–1919.45MHZ。但

    是其中251—255、77—82信道是测试信道,在实际中并不使用。所以它的实际有77个信道,频率范围从

    1895.15—1917.95MHZ。每个信道间隔300K。
    二、小灵通信号接收的流程是:天线将1900M频段的高频信号接受下来,通过带通滤波器进行信号滤波提纯提

    纯后的信号送入功放IC内部的天线开关电路,开关电路选通接收通路,信号再送入功放IC内部的混频器与一本

    振信号混频,之后由声表面滤波器窄带滤出243.95MHZ的中频信号243.95M的中频信号送入中频IC进行二次混

    频,233.15M的二本振信号由VCO2电路(一般由三极管、变容二极管组成)提供。混频后出来的是10.8M的信

    号,经过声表面滤波后,再进入中频IC内部处理后输出送到逻辑电路的CPU。
    当语音信号送入CPU进行QPSK解调,完成数字信号的TDMA时分多址分解、语音解码、数摸转换,解调出来的音

    频信号经过音频放大后,推动扬声器发出声音”。
    三、发射部分信号通路的流程
    发射信号的过程和接受信号的过程是一个相反的过程:
    由麦克风
    CPU内模数转换、调制编码
    中频处理IC


    功率放大
    天线开关
    天线
    语音被麦克风转变成电信号,经过音频放大后送入CPU进行A/D转换,将模拟信号转变成数字信号,同时CPU对

    此数字信号进行语音编码
    在CPU内部,语音信号经过信道编码交织、加密等工作,形成脉冲串,这些脉冲串被CPU组合形成TDMA数据流
    TDMA数据流在CPU中进行QPSK调制,调制后的信号为I+、I-、Q+、Q-四路信号。送入中频IC内部被调制到1.9G

    的待发射的高频信号,经过滤波、进行功率放大后,通过天线发射出去。

    随机整数的生成过程

      
     
     使用Java 2 SDK基础类库产生随机数的方法很多。但是如果你跟不上这些类库的更新脚步,你有可能正在使用的是一种低效的随机数生成机制,更糟糕的是:你有可能得到的不是均匀分布的随机数。本文将向你展示一种较为可靠的随机数生成方法,同时与其他方法进行比较。

      自从JDK最初版本发布起,我们就可以使用java.util.Random类产生随机数了。在JDK1.2中,Random类有了一个名为nextInt()的方法:
      public int nextInt(int n)
      给定一个参数n,nextInt(n)将返回一个大于等于0小于n的随机数,即:0 <= nextInt(n) < n。

      你所要做的就是先声明一个Random的对象,在调用其nextInt(n)函数以返回随机值。

      这里有个示例,下面的代码段将生成很多随机数并输出它们的平均值:

    以下是引用片段:
      int count = 1000000;
      int range = Integer.MAX_VALUE / 3 * 2;
      double sum = 0;
      Random rand = new Random();
      for (int i=0; i<count; i++) {
      sum += rand.nextInt(range);
      }
      System.out.println(sum/count);


      执行了1000000次循环之后,得到的平均值基本上就处于随机数范围的中点(midpoint)。

      到目前为止,事情还并不复杂,但是我们会问为什么要使用nextInt(n)?考虑一下的随机数生成方法:
      (1)使用老的方法nextInt(),没有制定数值范围
      (2)用Math.abs()静态函数得到(1)中产生值的绝对值
      (3)对(2)的结果进行取模运算(%),得到期望范围类的值

      我们说nextInt(n)要比上述方法更好,为什么呢?参考以下的代码段:

    以下是引用片段:
      sum = 0;
      for (int i=0; i<count; i++) {
      sum += Math.abs(rand.nextInt()) % range;
      }
      System.out.println(sum/count);


      不难发现,每次循环都多出了几步运算。事实上,这种随机数生成的方法存在着以下三个问题:

      首先,nextInt()返回的值是趋于均匀分布在Integer.MIN_VALUE 和 Integer.MAX_VALUE之间的。如果你取Integer.MIN_VALUE的绝对值,得到的仍然不是一个正数。事实上,Math.abs(Integer.MIN_VALUE)等于Integer.MIN_VALUE。因此,存在着这样一种情况(虽然很少见):rand.nextInt()=Integer.MIN_VALUE,经过取绝对值Math.abs(rand.nextInt())之后,得到是一个负数。这种几率为 1/(2^31),在我们的测试中不太可能发生——循环次数只有1000000次。
      其次,当你对nextInt()取模时,你使结果的随机性大打折扣。随机数中较小的值出现的几率更大一些。这就是众所周知的伪随机数生成,因此我们不是用取模的方法。
      最后,也可能是最糟糕的:随机数不是均匀分布。如果你执行了上述的两段代码,第一段代码的结果将会大于715,000,000,考虑到数值范围的中点(midpoint)是715,827,882,所以这是一个可以接受的结果。然而,你会吃惊的发现第二段代码得到的平均值肯定不会超过600,000,000。

      为何第二段代码的结果会如此的偏差?纠其本质,问题出在数值分布的不均匀。当你进行取模运算时,你将过大的数转换成了较小的。这使得较小的数更容易产生。

      使用nextInt(range)将会解决上述的三个问题。

      还有一种随机数生成方法——使用Math.random()。这个方法的效果如何?

    以下是引用片段:
      sum = 0;
      for (int i=0; i<count; i++) {
      sum += (int)(Math.random() * range);
      }
      System.out.println(sum/count);


    很好,使用random()不会碰到nextInt()的麻烦。你不会得到负数返回值,没有使用取模运算,值分布也是均匀的。还有什么问题吗?你有没有考虑到Math.random()使用了浮点运算,而nextInt()和nextInt(range)只有整数操作?Math.random()可能会慢上四倍。再加上从浮点到整数的类型转换,整个运算将会更慢。

      好了,经过一番比较,我们发现使用nextInt(range)生成随机数更为有效,因为它避免了其他方法的种种弊端。

      最后再给出一段代码,通过测试可以比较本文提到的几种随机数生成方法。

    以下是引用片段:
      import java.util.*;
      import java.text.*;

      public class RandomTest {
      public static void main(String args[]) {
      NumberFormat nf = NumberFormat.getInstance();
      int count = 1000000;
      int range = Integer.MAX_VALUE / 3 * 2;
      System.out.println("Midpoint: " + nf.format(range/2));
      double sum = 0;
      Random rand = new Random(); 
      for (int i=0; i<count; i++) {
      sum += rand.nextInt(range);
      }
      System.out.println("Good : " + nf.format(sum/count));

      sum = 0;
      for (int i=0; i<count; i++) {
      sum += Math.abs(rand.nextInt()) % range;
      }
      System.out.println("Bad : " + nf.format(sum/count));

      sum = 0;
      for (int i=0; i<count; i++) {
      sum += (int)(Math.random() * range);
      }
      System.out.println("Longer : " + nf.format(sum/count));
      }
      }

    java中LinkedList 集合类实现栈和队列

     
      栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表。

       LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素,和数组的顺序存储结构(如:ArrayList)相比,插入和删除比较方便,但速度会慢一些。

    栈的定义
         栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
      (1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
      (2)当表中没有元素时称为空栈。
      (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
         栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。

    实现代码:
    package com.gc.list;
    import java.util.*;
    public class MyStack {

     private LinkedList ll=new LinkedList();
     
     public void push(Object o){
      ll.addFirst(o);
     }
     public Object pop(){
      return ll.removeFirst();
     }
     
     public Object peek(){
      return ll.getFirst();
     }
     
     public boolean empty(){
      return ll.isEmpty();
     }
     
     public static void main(String[] args){
      MyStack ms=new MyStack();
      ms.push("zhangsan");
      ms.push("lisi");
      ms.push("wangwu");
      
      System.out.println(ms.pop());
      System.out.println(ms.peek());
      System.out.println(ms.pop());
      System.out.println(ms.empty());
     }
    }


    队列定义
         队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表

      (1)允许删除的一端称为队头(Front)。
      (2)允许插入的一端称为队尾(Rear)。
      (3)当队列中没有元素时称为空队列。
      (4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表。

    实现代码:
    package com.gc.list;
    import java.util.*;
    public class MyQueue {

     private LinkedList ll=new LinkedList();
     public void put(Object o){
      ll.addLast(o);
     }
     //使用removeFirst()方法,返回队列中第一个数据,然后将它从队列中删除
     public Object get(){
      return ll.removeFirst();
     }
     
     public boolean empty(){
      return ll.isEmpty();
     }
     
     public static void main(String[] args){
      MyQueue mq=new MyQueue();
      mq.put("zhangsan");
      mq.put("lisi");
      mq.put("wangwu");
      
      System.out.println(mq.get());
      System.out.println(mq.get());
      System.out.println(mq.get());
      System.out.println(mq.empty());
      
     }
    }

    DoJa平台手机游戏的开发与移植

     
    一,DoJa技术简介
           简单的说,DoJa是日本最大的移动通讯公司NTT DoCoMo的专利技术。而i-mode是该公司对于移动通讯2.5G阶段的一种应用模式,这个技术覆盖很多方面。i-mode初始于1999年,而i-mode与JAVA结合诞生的i-appli服务初始于2001年,以JAVA为开发语言的i-mode被称为DoJa技术,DoJa技术实际上是基于CLDC规范之上的平台技术,与J2ME标准平台是平行。有独立的API类库。在J2ME标准平台上开发的移动通讯程序叫做MIDP程序,符合MIDP1.0或2.0规范。而在DoJa平台上开发的程序被叫做appli程序。DoJa现在已经有很多版本。最高版本DoJa4.0。
     
     
    二,DoJaAPI预览
     
           我们以现在通用的DoJa2.5版本的API为例,大致看一下它有哪些特色。

    2.5版本包括下面几个包:
    包含了可以控制设备的类,比如camera类
    包含一些在CLDC的GCF( Generic Connection Framework)框架之下的类
    包含语言类
    包含了用于网络通讯方面的类
    包含了一些创建用户界面可选的类
    包含了可创建3D图形的类,也是可选的
    包含了一些可使用于本地终端功能的类,像操作手机电话本,收发Email等。
    包含了一些用于创建用户界面的类
    包含一些工具类
     
     
       可以看出DoJaAPI比标准J2ME更加丰富。一般在开发和移植过程中,经常遇到的类库就是com.nttdocomo.ui包,所以我们大致看一下这里面都有哪些类。
     
        这个包中包含了appli程序的入口类, Iapplication类,appli程序的用户界面(GUI)也分高级界面和低级界面,只不过他们的继承关系有些混乱,比如Component类是定义用于高级界面的抽象类,它有九个子类。包含一些按钮,标签,文本框的一些类。实际上就是一些组件。不是容器类。而Frame类也是一个抽象,意思是可表示为一个框架或容器。
        它的子类有Canvas,Dialog,Panel.其中Dialog和Panel属于高级界面类,而Canvas则用于低级界面。用于显示界面的类叫Display,而它的显示屏幕的方法为setCurrent(Frame f),里面的参数为Frame类对象。说明像Component类型的子类是不能独立显示在界面上的,要通过Frame子类中的高级界面类来填加。也就是必须放在Panel上面,才能被显示出来。
        其它的还有用于画图的Graphics,Graphics2D,Graphics3D类,负责加载媒体资源的MediaManager类等等。因为类很多,而且功能复杂和强大,就不一一介绍了,可以参考API文档进一步学习。
        三,appli程序开发
        下面我们通过一个小程序来讲解如何开发一个appli的程序。工欲善其事必先利其器,我们要下载一个DoJa的专用模拟器才行。
        好在DoJa的API文档和模拟器以及使用方法在http://www.doja-developer.net都已经给全了。下载对应DoJa2.5版本的模拟器。名字叫javaappli Development Kit for DoJa-2.5版本为 1.03,然后安装上就可以了。
        打开模拟器,会出现类似WTK的窗口,不同的是一个手机模拟器的窗口也会一起出现,而且还有个命令行模式的窗口。
        仔细看一下,其实界面功能挺简洁的,菜单栏有文件,工程,编辑,设备,帮助几个选择,工具栏包括新建项目,打开项目,ADF配置,创建,运行这些选项。下面还有一些运行模式的选择。当然这些项目都是英文的。
     
        什么是ADF配置呢,这里讲一下appli的安装程序也包括jar打包文件和一个描述文件,不同的是这个描述文件的类型为.jam.而ADF中的设置就是相当于WTK中的setting.也就是用于jam文件描述的项目。
     
        好了,我们先新建立一个工程,点new project,会出现一个提示窗口,让你输入工程名称,上面还有一个参考工程的选择,这个不用管它。我们的工程名就叫Test_doja. 点create创建。
       然后在这个窗口会显示一些我们创建的信息。比如我的模拟器安装路径是D盘根目录。那么会显示下面信息:
    Placed java source files in D:jDKDoJa2.5appsTest_dojasrc
    Placed resource files in D:jDKDoJa2.5appsTest_dojares
    Placed Scratchpad file in D:jDKDoJa2.5appsTest_dojasp
        说明在模拟器的apps目录下,就是我们创建的工程目录。里面还有三个文件夹,scr用来放.java文件,res用来放资源,sp用来存放Scratchpad文件。这个Scratchpad这里要详细讲一下。
     
       appli模式简单说就是客户手机通过连接 I – mode服务器来获得其它的网络资源。这些资源可以来自不同的网站。手机用单独有一块类似硬盘的区域用来存储这些资源,叫做Scratchpad,一般的DoJa手机游戏都是先从网络上下载资源到Scratchpad里,然后再从Scratchpad中读取来用。而且Scrtchpad是可写的,可以保存游戏信息。
     
       回到我们刚才的工程中,现在sp目录是空的,也就是没有Scratchpad文件。我们可以自己创建一个。默认名称是工程名后面加上数字0,Scratchpad文件的后缀名为.scr。
    需要说明的是,res目录里也是放资源文件的。所不同的是res中放的资源文件,在打包时会一起打进Jar文件。而sp目录下的Scratchpad不会。
     
       我们的程序很简单,所以就不用制作Scratchpad了。功能就是实现高级界面与低级界面的切换。下面是代码:
     
    import com.nttdocomo.ui.IApplication;
    import com.nttdocomo.ui.Canvas;
    import com.nttdocomo.ui.Panel;
    import com.nttdocomo.ui.Button;
    import com.nttdocomo.ui.Label;
    import com.nttdocomo.ui.ComponentListener;
    import com.nttdocomo.ui.Display;
    import com.nttdocomo.ui.Component;
    import com.nttdocomo.ui.Graphics;
     
     
    public class Test_doja extends IApplication implements ComponentListener
    {
           Panel p = new Panel();
          
           public Test_doja()
           {
                  Button ok = new Button("ok");
                  Label label = new Label("The first DoJa program!");
                  p.setBackground(0xc0c0c0);
                  p.add(label);
                  p.add(ok);
                  p.setComponentListener(this);           
           }
           public void start()
           {
                  Display.setCurrent(p);
           }
           public void componentAction(Component source, int type, int param)
           {
                  if(type == ComponentListener.BUTTON_PRESSED)
                  {
                         Display.setCurrent(new DoJaCanvas());
                  }
           }
     
    }
     
    class DoJaCanvas extends Canvas
    {
           public DoJaCanvas()
           {
           }
           public void paint(Graphics g)
           {
                  g.setColor(0xff0000);
                  g.fillRect(0,0,getWidth(),getHeight());
                  g.setColor(0xffffff);
                  g.drawString("Hello world!",30,50);
           }
    }
     
     
     
        代码很简单,所以我没加注释,有过J2SE和J2ME编程经验的人,应该很容易看懂。Iapplication类跟MIDlet性质相同。不过它只需要从写start()方法,作为程序启动入口。
    我们现在把代码保存在scr文件夹中,然后点build,如果没错误,则会提示下面信息:
    D:jDKDoJa2.5appsTest_dojabinTest_doja.jar created
    D:jDKDoJa2.5appsTest_dojabinTest_doja.jam updated
    Build completed
     
    说明jar和jam文件直接创建完了。然后点run,就可以看效果了。是不是很轻松。: )
     
     
    四, DoJa游戏移植到J2ME平台的方法
     
           这部分内容我在手机移植体会(二)中已经介绍过,这次我主要说一下资源文件的读取。其实DoJa的API比标准J2ME丰富许多,所以移植是有难度的。用标准的J2MEAPI类库不能完全实现DoJa类库所有功能。我主要说一下一般的移植方法。
    前面讲过关于Scratchpad的概念。我们通常看到的工程文件,都包含很多内容。其中有gif资源文件,.scr文件,和代码。我觉得只有.scr文件和java代码和打包后的jam和jar文件就够用了。因为图片和声音文件通常也在.scr文件中包含。不过有些小游戏的一些图或声音也会直接打在jar包内。就是工程中res目录下的东西。。
     
    关于.scr文件的读取与解析,DoJa都提供了详细的方法,比如:
     
    DataInputStream in = Connector.openDataInputStream(
              "scratchpad:///0;pos=" + offset+ ",length=" + length)
     
    实际表示 从 scratchpad 的第 0 扇区 偏移量为offset,长度为length的数据作为 输入流。
    前面我们说了scratchpad像硬盘一样。所以scratchpad:///0 的0 也可以是1 或者别的数字。但是区域不同。0对应的Scratchpad文件名为"工程名"+0.scr,如果是1就是"工程"+1.scr.也就是说Scratchpad可以由多个文件组成表示不同的存储区域.如果是往scratchpad中写操作,就用DataOutputStream构建就可以了。比如保存游戏中的分数。
    上面这是从scratchpad中得到资源文件在DoJa代码中的写法。如果要是从res目录中读取,如何写呢。像这样:
    DataInputStream in  is = Connector.openInputStream("resource:///" + filename);
    filename就表示资源文件的名字。
     
        看了上面的表示方法,我想大家应该会用J2ME的方法来把他们从写了吧。DoJa读取资源的方法很灵活,比如gif图片,可以直接用文件名得到图片对象,也可以用byte数组构建,不过比较常用的,还是用输入流来构建。所以移植中要修改图片,首先要对.scr文件进行分析,解析,将图片整理出来,才能使用。提取图片的方法,可以参考我BLOG中的一个程序。
     
        在IApplication类中有个很重要的方法 getArgs() ,这个方法会得到 jam描述文件中App param项目的参数,这些参数可以用空格分开,每一段就表示一个元素,因为用getArgs()得到的是一个String的数组。所以很多游戏都是靠jam中的App param参数进行初始化资源,或判断。
     
        把资源文件找到后,就可以对游戏进行修改了,不过有些方法需要你自己从写,比如drawImage 有很多参数的方法,可以从大图中画小图, 还有 doja自己按键处理机制。不过这些如果仔细看API的话,是可以用J2ME从写的。 有些实现不了的功能,就可以注释掉了。
     
        以上就是我对移植DoJa游戏的一点建议。有些在手机游戏移植体会(二)里面已经说过的我就没有再提。如果你在移植中遇到什么问题可以向我咨询,我会努力帮助你。
     
     
    五,相关资源链接
    http://www.doja-developer.net   可以下载模拟器,API文档,以及DoJa技术的介绍等
     
     
    http://www.nttdocomo.com     NTT DoCMo 公司的官方网站,里面介绍一些最新的技术和I-mode 的介绍。
    March 25

    JAVA汉化教程

    一:JAVA游戏分析
          大家从网上下载的一般都是JAR格式的游戏.下载后用WINRAR打开.解压后JAVA游戏一般包括几个文件.例如我汉化的超级玛丽豪华汉化版


       COM文件夹里主要存放各公司的文件.网上流传用COM包移植NOKIA的游戏.就是说这个COM包.
       icons文件夹里面存放的就是图标文件.图标文件用PNG格式存放.
       META-INF文件夹主要存放MANIFEST.MF文件.要改游戏文件名为中文名就是修改MANIFEST.MF文件.
        level2.map等文件就是地图文件.一般不用进行修改.不必理会.
       lang文件就是语言包.一般游戏文字资源主要存放于lang.×.class.*.dat还有*.txt文件
        其中如果文字资源包含在lang.和*.txt最方便汉化.因为汉化lang用工具可以直接修改.*.txt可以用记事本打开修改.
       还有就是游戏的图片文件了一般以PNG图片文件为主.



    二:汉化工具
       我常用的JAVA汉化工具有四个.分别是hhclass.UEDIT32.Hex2Text.CrPNG-2这四个工具.
       一.hhclass主要是用来汉化class.语言包和文件名的.这款软件一般的文字资源都能找到.但是有一个缺陷.大部分比较长的文字资源.
    大于250文字都不能找到.例如有游戏的帮助文字
       二.UEDIT32.这个大家都熟悉.经典的十六进制编辑工具.用来完美汉化JAVA最合适不过了.我平时主要用来修改一些hhclass不能搜索到的文字资源.
       三.第三个是Hex2Text.这是小海开发的十六进制辅助工具.主要是用来转换编码.由于JAVA是采用UTF-8编码的.要汉化就必须文本转换到UTF8再转换到16进制
       四.第四个是CrPNG-2.主要用来提取PNG格式图像的.由于JAVA体积小.游戏中使用的图片格式都是PNG格式.要实现完美汉化就必须连一些图片资源也汉化.这 个工具就能快速的对资源文件搜索出PNG图片.不过这软件我还未成功搜索一次图片.最后一个软件CrPNG-2也是小海开发的.主要是用于内部交流.我跟小海要了个免注册版.汉化组有需要的兄弟可以跟我要.其他兄弟如果对汉化JAVA有兴趣可以用GOOGLE搜索一下


    三.使用工具汉化.
       一.进行汉化前先装好模拟器.不然一变一变从手机上测试就很麻烦了.我使用的模拟器是midpx_java..这个模拟器能模拟95%的JAVA游戏.安装后开始汉化.
       二.从下载英文版游戏下载英文版游戏.下载后用WINRAR解压
    然后使用hhclass工具汉化.打开hhclass后选择打开语言包.打开超级玛丽豪华版文件夹的lang文件.打开后会看到界面上显示



    这些文件就是游戏中的文字资源.装好了JAVA模拟器系统会自动关联jar和jad格式.双击超级玛丽豪华版的jar文件就会弹出模拟器的窗口.


    这就是电脑上模拟出来的效果.看到了游戏的英文文字了吗?我们一起把它消灭掉...


    接下来切换窗框到hhclass.看看这些英文单词就是游戏中的文字.只要简单的把它改为中文就可以了.例如点击"sound off"在下面的白色对话框
    输入“关闭声音"然后点击替换.再点击保存文件.



    然后我们用右键点击超级玛丽豪华版.JAR.弹出菜单”打开为“选择WINRAR打开方式.用WINRAR打开.打开后.在WINRAR软件界面中.点击”添加-选择刚汉化的LANG文件-点击确定.这样我们刚刚汉化的LANG文件也就添加进超级玛丽豪华版.JAR文件去了.或者你可以用WINRAR打开超级玛丽豪华版.然后直接把刚才汉化的LANG文件拖进压缩包里.具体步骤我就不再多说了.

    接下来把全部英文资源汉化完.我们要测试一下汉化了没有.直接双击打开超级玛丽豪华版.JAR.弹出模拟器窗口.看一下效果.

    对于中文名的汉化.我们只要用hhclass工具.选择“打开MANIFEST”打开刚超级玛丽豪华版文件夹中的META-INF文件夹.再打开MANIFEST.MF文件你就会看到:

    手机SIM内部资料介绍

    什么是SIM卡

    移动电话机与SIM卡共同构成移动通信终端设备。无论是GSM系统还是CDMA系统,数字移动电话机用户在“入网”时会得到一张SIM卡。SIM卡 是(Subscriber Identity Model客户识别模块)的缩写 ,也称为智能卡、用户身份识别卡, GSM数字移动电话机必须装上此卡方能使用。

    SIM卡就是一个在内部包含有大规模集成电路的卡片,卡片内部存储了数字移动电话客户的信息、加密密钥等内容,它可供GSM网络对客户身份进行鉴别,并对客户通话时的语音信息进行加密。SIM卡的使用,完全防止了并机和通话被窃听行为,并且SIM卡的制作是严格按照GSM国际标准和规范来完成的,它使客户的正常通信得到了可靠的保障。现在的数字电话都是必须要安装SIM卡之后才可以使用,如果不安装的话,那么后果相信也就也不用我多说了。在没有安装SIM卡的情况下,我们仅仅只能拨打像119、112这种紧急电话的号码。

    SIM卡在GSM系统中的应用,使得卡和手机分离,一张SIM卡唯一标识一个客户。一张SIM卡可以插入任何一部GSM手机中使用,而使用手机所产生的通信费用则自动记录在该SIM卡所唯一标识的客户的帐户上

    PIN、PUK码介绍
    我们在使用手机时,会接触到5种密码 :SIM卡的PIN、PIN2、PUK、PUK2和手机密码。前四种初始密码都是SIM卡供应商移动、联通提供的,手机密码是手机生产商提供的。它们之间的关系如下:

    1、PIN码(即PIN1码)就是SIM卡的个人识别密码 ,一般在修改前原始密码是1234,如果不是就不要再试了,打1860/1001咨询。打开开机PIN码,刚每次开机后就要输入PIN码!如果输入三次错误,需要用PUK码 解锁,PUK码 由移动、联通提供,如果输入十次错误会导致SIM卡烧毁,所以有问题不要自己随便猜测密码 ,马上找移动、联通。

       2、PIN2码是设定手机计费时使用的,如果输入三次错误需要用 PUK 2码解锁。目前移动、联通都不提供此项功能支持,即使PIN2密码锁死也不会影响手机正常使用。

       3、PIN码连续输入10次都是错误的话就会锁卡要求用PUK码 来解开,而PUK码的输入机会只有3次,3次都输错的话,SIM卡将会给永久锁死,即报废了。

       4、PUK码,不管你使用的是全球通还是神州行,网络服务商那里都有资料保存,一旦需要输入时,可以致电相应的服务热线来查询,先核对用户资料就行了。这些密码设定及更改都在菜单-其他设定-安全设定中。

        忘记PIN码可以用PUK码来解密,PUK密码一般不向用户提供,但某些SIM卡除外,比如神州行的用户就随卡提供PUK。如果你的SIM卡的PUK没有随卡提供,你可以到当地的网络运营商营业厅要求解锁,一般是免费的。

    SIM外观
    在实际使用中有两种功能相同而形式不同的SIM卡:卡片式(俗称大卡)SIM卡,这种形式的SIM卡符合有关IC卡的ISO7816标准,类似IC卡;嵌入式(俗称小卡)SIM卡,其大小只有25mm×15mm,是半永久性地装入到移动台设备中的卡。

    “大卡”上真正起作用的是它上面的那张“小卡”,而“小卡”上起作用的部分则是卡面上的铜制接口及其内部胶封的卡内逻辑电路。目前国内流行样式是“小卡”,小卡也可以换成“大卡”(需加装一卡托)。“大卡”和“小卡”分别适用于不同类型的GSM移动电话,早期机型如摩托罗拉GC87C、308C等手机用的是“大卡”,而目前新出的机型基本上都使用“小卡”

    在SIM卡的背面有以五个一排,被排成四排的一组数字,在这组数字最前面的六位数字所代表的是中国的代号,就像从国外打电话到国内都需要先拨打86一样。第七位数字则代表的是接入号码,如果是5的话,那么这张SIM卡的电话号码前三位就是135的,而如果是6的话,则代表其前三位数字为136,其它的也都以此类推。第八位数字代表的是该SIM卡的功能位,一般情况下显示的数字为0。第九和第十位数字代表了该SIM卡所处的省份。至于第十一和第十二位数字则代表的是该SIM卡的年号,而第十三位数字则是SIM卡供应商的代码。从第十四位开始至第十九位数字则代表了该SIM卡的用户识别码。最后一个数字是校验位。

    什么是Ki、IMEI、IMSI
    国际移动设备识别码(IMEI:International Mobile Equipment Identification Number)是区别移动设备的标志,储存在移动设备中,可用于监控被窃或无效的移动设备。IMEI组成如下图所示,移动终端设备通过键入“*#06#”即可查得。其总长为15位,每位数字仅使用0~9的数字。其中TAC代表型号装配码,由欧洲型号标准中心分配;FAC代表装配厂家号码;SNR为产品序号,用于区别同一个TAC和FAC中的每台移动设备;SP是备用编码。

    国际移动用户识别码(IMSI:International Mobile Subscriber Identification Number)是区别移动用户的标志,储存在SIM卡中,可用于区别移动用户的有效信息。IMSI组成如下图所示,其总长度不超过15位,同样使用0~9的数字。 其中MCC是移动用户所属国家代号,占3位数字,中国的MCC规定为460;MNC是移动网号码,最多由两位数字组成,用于识别移动用户所归属的移动通信网;MSIN是移动用户识别码,用以识别某一移动通信网中的移动用户。

    Ki (Key identifier)是SIM卡与运营商之间加密数据传递的密钥。GSM的加密方式是一种称为comp-128的数字加密运算,当系统进行验证时会同时使用Ki及IMSI,经过一连串系统安全认证讯息后产生随机变量,并以A3算法进行加密运算与手机内存资料进行比对,当身份确认无误后始可入网。目前GSM使用的Ki长度是16 bytes,相当于128bits,若非经过特殊译码程序,使用者无法读取Ki,安全性极高,使用者无须担心有被盗打电话的顾虑。

    由此看来,只要知道SIM卡的Ki、IMSI值,我们就可以通过软件仿真出SIM卡的功能,甚至可以利用多组Ki、IMSI值,用一张微处理器卡片来同时仿真本来需要多张SIM所完成的功能,这就是“一卡多号”技术。

    SIM卡的软件特性
    SIM卡采用新式单片机及存储器管理结构,因此处理功能大大增强。其智能特性的逻辑结构是树型结构。全部特性参数信息都是用数据字段方式表达,SIM卡中存有3类数据信息:

    1. 与持卡者相关的信息以及SIM卡将来准备提供的所有业务信息,这种类型的数据存储在根目录下;

    2. GSM应用中特有的信息,这种类型的数据存储在GSM目录下;

    3.   GSM应用所使用的信息,此信息可与其他电信应用或业务共享,位于电信目录下。

    在SIM卡根目录下有3个应用目录,一个属于行政主管部门应用目录,另外两个属于技术管理的应用目录,分别是GSM应用目录和电信应用目录。所有的目录下均为数据字段,有二进制的和格式化的数据字段。数据字段中的信息有的是永存性的即不能更新的,有的是暂存的需要更新的。每个数据字段都要表达出它的用途、更新程度、数据字段的特性。

    SIM卡内部的数据
    了解完SIM卡的大概之后,我们再来看看SIM卡具体都能存储哪些类型的数据。以目前的情况来看,SIM卡能够存储的数据类型主要被分为以下四种:

    1. 由SIM卡生产厂商存入的系统原始数据

    2. 存储手机的固定信息,手机在出售之前都会被SIM卡中心记录到SIM卡当中,主要包括鉴权和加密信息、国际移动用户识别码(IMSI)、IMSI认证算法、加密密匙生成算法、密匙生成前,用户密匙的生成算法(这三种算法均为128位)

    3. 用户自己存入的数据,如短消息、固定拨号、缩位拨号、性能参数、话费记数等;能够存储有关的电话号码,也就是具备电话簿功能。

    4. 有关于网络方面的数据,用户在用卡过程中自动存入和更新的网络接续和用户信息类数据,包括最近一次位置登记时手机所在位置识别号、设置的周期性位置更新间隔时间、临时移动用户号等。不过这种数据的存放是暂时性的,也就是说它并不是永久的存放于SIM卡之中。

      5.相关的业务代码,这一点相信也是大家很熟悉的,那就是非常重要的个人识别码(也就使我们平常所说的PIN码),还有就  是解开锁定用的解锁码(PUK)等等。

    以上四种类型的数据都是存储在SIM卡当中的,而我们通常也是可以利用这些数据来进行手机的设置,每张SIM卡个人密码(PIN)都是可以由用户设置,利用加密的功能可以实现防止手机被其它人所盗用甚至被窃听,由此看来SIM卡不仅仅可以为我们提供打电话的功能,而且还为我们保护自己的隐私而提供了安全的保障。

    SIM卡内部的数据都存放在各自的目录项内,第一类数据放在根目录,当电源开启后首先进入根目录,再根据指令进入相关的子目录,每种目录及其内部的数据域均有各自的识别码保护,只有经过核对判别以后才能对数据域中的数据进行查询、读出和更新。上面第一类数据通常属于永久性数据,由SIM卡生产厂商注入以后无法更改,第二类数据只有网络运行部门的专门机构才允许查阅和更新,第三、四类数据中的大部分允许用户利用手机对其进行读写操作。

    SIM卡的类型
    SIM卡的存储容量有3kB、8kB、16kB、32kB、64kB等。STK卡(SIM application Tool Kit)是SIM卡的一种,它能为手机提供增值服务,如移动梦网业务等。SIM卡能够储存多少电话号码和短信取决于卡内数据存储器EEPROM的容量(有2KB、3KB、8KB容量),假设一张EEPROM容量为8KB的SIM卡,可储存以下容量的数据:100组电话号码及其对应姓名、15组短信息、25组最近拨出的号码、4位SIM卡密码(PIN)。目前中国移动/中国联通实际对普通用户提供的多数是普通8K的SIM卡。

    SIM卡的接口
         SIM卡是通过卡面上铜制接口来连接卡内逻辑电路与移动终端的,SIM卡芯片有8个触点,通常与移动设备连接需要6个触点。

    SIM卡是一个装有微处理器(CPU)的芯片卡,它的内部有5个模块,并且每个模块都对应一个功能:微处理器CPU(8位)、程序存储器ROM(3~8kbit)、工作存储器RAM(6~16kbit)数据存储器EEPROM(16~256kbit)和串行通信单元。这5个模块被胶封在SIM卡铜制接口后与普通IC卡封装方式相同。这5个模块必须集成在一块集成电路中,否则其安全性会受到威胁,因为芯片间的连线可能成为非法存取和盗用SIM卡的重要线索。

    SIM卡的供电分为5V(1998年前发行)、5V与3V兼容、3V、1.8V等,当然这些卡必须与相应的手机配合使用,即手机产生的SIM卡供电电压与该SIM卡所需的电压相匹配。SIM卡插入手机后,电源端口提供电源给SIM卡内各模块。

    手机开发平台指南、教程和资料介绍

    近来无事,把手机开发平台的学习指南、教程和资料总结一下,方便大家参考。
    手机客户端软件开发最大的困难就是平台不统一,手机开发平台太多。
    手机可分为智能手机开发和feather phone手机。开发平台可分为开放式平台和封闭式平台,开放式平台包括symbian、windows mobile、linux、Android、BlackBerry、j2me、brew等,支持手机应用程序通过OTA下载和安装;封闭式平台包括MTK、展讯、TI、飞利浦等。下面分别介绍。
    1. Symbian
    Symbian平台为目前智能手机市场的老大,智能手机全球市场占70%以上,在欧洲和亚洲占绝对优势,只是在美国市场份额少得可怜,希望今年nokia在美国发力,赶上其它智能手机。根据UI风格的不同,Symbian分为s60和UIQ两个平台,其中nokia使用s60平台,索爱和moto采用UIQ平台。Symbian平台由于发展时间较长,又是市场老大,目前中文资料也较多,不像几年前刚接触时只有英文资料。以下书籍值得推荐:
    SYMBIAN OS软件开发开发--应用C++开发智能手机应用程序入门》(其中UI部分为UIQ平台),
    《Series 60 应用程序开发》(以s60平台为主,重点推荐)
    Symbian OS C++手机应用开发 (第2卷)》
    另外今年将出来一本有关uiq3.0的新书,值得期待。
    关于symbian的开发网站和论坛:
    诺基亚论坛:最好的symbian论坛,
    http://discussion.forum.nokia.com/forum/forumdisplay.php?f=6,其中还有中文论坛。
    UIQ官方论坛:http://developer.uiq.com/
    Symbian公司中文论坛:http://developer.symbian.com/forum/forum.jspa?forumID=37
    NewLC网站:http://www.newlc.com/
    索爱uiq官方论坛:http://developer.sonyericsson.com/category.jspa?categoryID=3
    索爱uiq中文论坛http://developer.sonyericsson.com/forum.jspa?forumID=133

    2.windows mobile:
    智能手机全球市场中windows mobile占12%左右市场份额。开发与windows平台类似,所以熟悉windows开发的能很快上手。目前没有较好的针对windows mobile的书,经典书籍《Windows 程序设计(第5版)》对于开发win32程序依然是最好的,经典的书就是牛啊!虽然pocket pc支持MFC,但smartphone不支持,所以为了更好的移植,用win32开发较好。由本书做基础,再参考windows mobile的sdk以及示例代码,应该能很快上手。
    关于windows mobile的开发网站和论坛:
    Windows mobile中文社区:http://www.winbile.net/BBS/
    Pocket pc forum:http://www.windowsmobiledn.com/forum/
    微软官方网站:http://www.microsoft.com/windowsmobile/developers/default.mspx

    3. linux:
    智能手机全球市场中linux手机仅占可怜的4.4%市场份额。原来moto还出过不少linux手机,如A768、A1200、E680、E2、E6、V8等,07年8月份还信誓旦旦预测60%手机采用Linux OS,但moto后来回购了UIQ的股份,又与微软合作,还加入了google的开放手机联盟,看来要抛弃自己的linux平台了。另外,moto的策略是linux+j2me的模式,虽然采用linux os,但并不对外开放linux的sdk,只有和moto合作的厂家才能获得native linux sdk,所以导致目前linux手机开发的资料和论坛较少。虽然有民间linux高手破解了moto的linux的sdk,可以开发native linux的程序,但native linux的程序不能直接安装在moto的linux手机上,还必须安装一个插件,这对普通用户又是难以跨越的一个门槛。所以个人觉得native linux手机的开发将走向末路。大部分linux手机的ui开发都是基于QT,关于QT开发,可参考《C++ GUI Qt3编程》、《精通Qt4编程》,如果有moto官方的sdk,参考API文档以及一些示例代码,将可以较快上手,如果没有官方的sdk,那就要话很长时间hack了。目前没有很好的关于linux手机开发的论坛,个人推荐陈罡的博客http://www.cublog.cn/u/26691/,内有moto a1200开发随笔,对于熟悉和了解手机native linux开发有很大帮助。

    4. MTK:
    MTK最近几年异军突起,近70%的国产手机采用MTK的芯片和平台,黑手机更几乎是MTK的代名词。国内厂家只有夏新没有采用MTK的方案。MTK的模式名为“Turn-key”的全面解决方案,厂商采用了这个方案,只需要加一个手机外壳即可成品——这能大大降低了出货时间,一般厂家只修改界面、铃声以及增加一些应用软件。有关MTK平台的介绍,见环球企业家杂志的文章“国产手机操纵者联发科的秘密”http://www.cnbeta.com/articles/45580.htm
    MTK是私有平台,目前没有书籍介绍MTK平台,所以只能从网上查找MTK的资料。以下资料大家可以从网上获得,对于了解MTK很有帮助:《mtk 训练课程.pdf》、《MMI Platform Source Code Training.pdf》主要是MMI界面开发介绍、《MMI Resource & Customization Tool.pdf》MMI资源工具介绍。
    最近,MTK平台MMI设计牛人FUGUI自己编写了一本有关mtk平台MMI开发的实例教程,书名为《MMI实例培训教程》(本书大家通过Google下载到),此书深入浅出,全面的介绍了MTK平台MMI开发的各个方面,通过本书,开发人员将能很快进入MTK平台开发领域,实为MTK平台MMI开发的圣经!MTK平台的操作系统为nucleus,有关nucleus的介绍网上有一篇文章《Nucleus实时操作系统分析报告》。MTK平台主要用C语言开发,所以要熟悉MTK开发,首先必须熟悉掌握C语言,MTK的sdk与vc6集成,MMI的各控件和窗口之间通过回调函数实现通讯。
    关于MTK的开发网站和论坛:
    我爱研发网:http://www.52rd.com/ 上面几篇文章和书籍都能从本网站找到。
    手机研发论坛:http://www.1mp.cc/bbs/index.asp


    5. 展讯:
    展讯平台07年也发展很快,利用MTK下半年PA放大器缺货的机会,趁势而入,抢走mtk很多市场份额。展讯的开发模式和MTK的很类似,基本也是给厂家提供整体解决方案,与MTK的差别见此链接http://www.chinabyte.com/telecom/267/2507267.shtml。国内主要是夏新、联想、文泰等采用展讯平台。展讯平台采用的嵌入式操作系统是threadx,关于threadx的有一本中文书《嵌入式实时操作系统的多线程计算:基于ThreadX和ARM》。同MTK平台一样,为封闭平台,开发语言为C,开发环境为vc6, MMI的各控件和窗口之间与windows类似通过消息进制实现通讯。另外也没有书籍介绍展讯平台,以下资料值得推荐:
    《Spreadtrum_SAP.ppt》
    《MMK_Kernel软件API接口说明书.doc》
    《MMK_Window_Table开发说明书.doc》
    《展讯平台MMI窗口开发说明书.pdf》
    《展讯手机平台软件简介.pdf》
    关于展讯的开发网站和论坛:
    我爱研发网:http://www.52rd.com/ 上面几篇文章都能从本网站找到。
    手机研发论坛:http://www.1mp.cc/bbs/index.asp

    6. J2ME:
    J2ME平台为手机上运用最广泛的开放式平台,绝大部分手机均已经支持J2ME了。关于J2ME的书籍数不胜数,个人推荐以下书籍:
    《j2me技术手册》
    《J2ME开发大全》
    《J2ME移动应用程序开发》
    关于J2ME的开发网站和论坛:
    J2ME开发网:http://www.j2medev.com/Index.html
    中国Java手机网:http://www.cnjm.net/
    以及各手机厂商的官方java论坛

    7. Brew
    Brew 的全称是无线二进制运行时环境。Brew平台是高通公司开发的,从无线应用程序开发、设备配置、应用程序分发以及计费和支付的完整端到端解决方案中的无线应用程序开发部分。目前绝大部分CDMA手机都支持Brew平台。学习Brew平台,首先需要熟悉c语言。学习步骤和方法可参考” BREW高手之路-解析BREW学习过程”。
    学习书籍:
    《深入BREW手机游戏开发》
    《BREW 技术开发与应用》
    这些书虽然不够深入,但对于入门还是可以参考的。
    关于Brew的开发网站和论坛:
    Brew官方论坛:http://brewforums.qualcomm.com/index.php

    8. Blackberry,Android,iPhone
    黑莓公司BlackBerry手机和Google的Android手机均只支持java开发。苹果的iPhone不支持第3方开发,只能开发网页,据说将来开放sdk,值得期待。
    BlackBerry的开发网站和论坛:
    BlackBerry开发者指南:http://www.cnblogs.com/confach/category/36451.htmlBlackBerry官方网站:http://na.blackberry.com/eng/developers/community.jsphttp://bbs.maxpda.com/forum-184-1.html
    Android的开发网站和论坛:
    http://www.androiddev.net.cn/bbs/
    http://www.androidin.com/http://www.androidcn.net/
    iPhone的开发网站和论坛:
    一群苹果fans成立的网站:http://apple4.us/
    http://bbs.maxpda.com/forum-190-1.html
    http://lordhong.javaeye.com/blog/153315
    http://lordhong.javaeye.com/blog/152774

    9. 其它Feather phone平台
    其它feather phone平台,如TI、飞利浦、英飞凌(Infineon)、飞思卡尔(Freescale)、Broadcom、Skyworks等平台,由于平台私有,并且不提供第三方sdk,所以也没有相关资料和文档,希望有了解的朋友介绍一下。
    March 23

    J2ME 2D小游戏入门之周边工具类


    完善周边工具类(图象、GameObject、Font)

      虽然我们有了midp2.0的支持,但是有时还是需要一些辅助工具,方便我们使用。这怕是在进行真正的游戏设计之前最有趣的了。

      1、首先是一个ImageTools工具类,提供一个方法帮助调用Image



    public class ImageTools {
     protected ImageTools() {}

     public static Image getImage(String str){
      Image img=null;
      try {
       img = Image.createImage(str);
      }
      catch (Exception ex) {
       System.out.println(ex);
      }
      finally{
       return img;
      }
     }
    }




      2.GameObject,提供一个通用的游戏对象。

      有了Sprite类,为什么还要GameObject呢?其实我们一般是将Sprite,看作成一个高级的Image,往往一个Sprite要被多个 游戏对象调用,GameObject其实就是Sprite的状态类。GameObject提供简单的生命周期概念,动画更新速度;



    public class GameObject {
     public Sprite sprite;//内置的Sprite
     public boolean alive;//存活标记
     private int lifecount=0;//生命周期计数器
     public int lifetime=0;//生命周期,以桢为单位
     public int speed=0;//动画桢更新速度,(0至无穷,0代表每一桢跟新一个画面)
     private int animcount=0;// /动画桢更新计数器
     public GameObject(Image img,int width,int height){
      sprite=new Sprite(img,width,height);
      reset();
     }
     public void move(int dx,int dy){//相对移动
      sprite.move(dx,dy);
     }

     public void moveto(int x,int y){//绝对移动
      sprite.setPosition(x,y);
     }

     public void update(){//更新状态,动画桢更新,生命周期更新
      if(!alive)
       return;
      if(++animcount>speed){
       animcount=0;
       sprite.nextFrame();
       if(lifetime!=0 && ++lifecount>lifetime)
        alive=false;
      }
     }

     public void paint(Graphics g){//Paint
      if(!alive)
       return;
       sprite.paint(g);
     }

     public void reset(){//复位
      alive=true;
      lifecount=0;
      animcount=0;
      sprite.setFrame(0);
     }
    }





      3.封装字体类,你需要漂亮的字体吗?

      我们经常需要用图片来输出文字,一个方便的字体类是必须的。我们希望仅仅提供一个图片,一个图片所描述的字符的数组,来初始化一个字体类。字体类提供一个类似Textout的方法,方便得在一个位置输出信息。先封装一个简单的版本,只支持英文和数字,并且输出不能自动换行。 可能你有一个简单的思路,就是简单的保存字符数组,当打印的时候遍历数组,来查找每个字符在sprite的frameseq中的index,但当我们打印 一个字符串的时候就会发现,太多的遍历操作耽误了宝贵时间,这里我们使用一个小技巧用容量换取速度,我们知道Character. hashCode()可以返回字符的ascii编码,常用字符将返回1-127;利用这一点,我们开辟一个128的数组charhash,将输入的字符c所在图片index存入charhash[c. hashCode()]中。以后也用这种映射方法来读取字符。charhash的元素初值为-1,以后只要数值大于0就是有效值。



    public class Font {
     Sprite sprite; //Sprite
     int width,height; //每个char的尺寸
     int[] charhash; //储存1-127个常见字符在sprite的frameseq中的位置
     Graphics g;
     public Font(Graphics g,Image img, int width, int height, char[] chars) {
      this.g=g;
      sprite=new Sprite(img,width,height);
      this.width=width;
      this.height=height;
      charhash=new int[128];
      for (int i = 0; i < charhash.length; i++) {
       charhash=-1;//没有代表此字符的图片
      }
      Character c;
      for (int i = 0; i < chars.length; i++) {
       c=new Character(chars);
       charhash[c.hashCode()]=i;
      }
     }
    public void drawChar(char ch, int x, int y){
     Character c=new Character(ch);
     int hashcode=c.hashCode();
     sprite.setPosition(x,y);
     if(hashcode>=0){
      sprite.setFrame(charhash[hashcode]);
      sprite.paint(g);
     }
    }

    public void drawString(String str, int x, int y){
     int length=str.length();
     for (int i = 0; i < length; i++) {
      drawChar(str.charAt(i),x+width*i,y);
     }
    }

    }




      这样只要有一个实例font,就可以调用font.drawString(“hello”,0,0);

      在0,0位置输出漂亮的图片字符串。怎么样还挺好使的吧。

    备份 资源


    J2MEGAME网站上有很多资源 包括 图片 声音 工具

    以下是其中的游戏制作工具区的网址 里面有很多编辑器 好东西呀 大笑
    http://www.j2megame.cn/forumdisplay.php?fid=36

    一个音乐播放的工具类

    //引入媒体包
    import javax.microedition.media.*;
    //引入控制包
    import javax.microedition.media.control.*;
    //读取资源使用
    import java.io.*;

    public class LPAudioPlayer {
            /** 媒体接口 */
            private Player player;

            /** 播放的媒体文件名 */
            private String filename;

            /** 播放的媒体格式 */
            private String format;

            /**
             * 媒体播放类构造方法
             *
             * @param filename传入媒体的文件名
             * @param format文件格式
             * @param isLoad是否立刻装载媒体
             */
            public LPAudioPlayer(String filename, String format, boolean isLoad) {
                    this.format = format;
                    this.filename = filename;
                    if (isLoad) {
                            loadResource();
                    }
            }

            /**
             * 媒体构造方法
             *
             * @param filename文件名称
             * @param format文件格式
             */
            public LPAudioPlayer(String filename, String format) {
                    this.format = format;
                    this.filename = filename;
            }

            /**
             * 装载媒体资源
             *
             */
            public void loadResource() {
                    try {
                            // 根据文件名称创建流对象
                            InputStream is = getClass().getResourceAsStream("/" + filename);
                            // 创建播放器接口
                            player = Manager.createPlayer(is, format);
                    } catch (IOException e) {
                            System.out.println("can't load " + filename);
                            System.out.println(e);
                    } catch (MediaException e) {
                            System.out.println("can't create audio");
                            System.out.println(e);
                    }
            }

            /**
             * 设置循环播放
             *
             */
            public void setLoop() {
                    if (player != null) {
                            player.setLoopCount(-1);
                    }
            }

            /**
             * 设置音量
             *
             * @param level音量大小
             */
            public void setVolume(int level) {
                    if (player != null) {
                            VolumeControl control = (VolumeControl) player
                                            .getControl("VolumeControl");
                            control.setLevel(level);
                    }
            }

            /**
             * 停止播放
             *
             */
            public void stop() {
                    if (player != null) {
                            try {
                                    player.stop();
                            } catch (MediaException e) {
                                    System.out.println("can't stop audio");
                                    System.out.println(e);
                            }
                    }
            }

            /**
             * 播放方法
             *
             */
            public void play() {
                    if (player != null) {
                            try {
                                    // 获得播放信息
                                    player.realize();
                                    // 获取稀有资源
                                    player.prefetch();
                                    // 开始播放
                                    player.start();
                            } catch (MediaException e) {
                                    System.out.println("can't play audio");
                                    System.out.println(e);
                            }
                    }
            }

            /**
             * 重新播放声音文件
             *
             */
            public void replay() {
                    // 关闭当前声音接口
                    close();
                    // 进行垃圾回收
                    System.gc();
                    loadResource();
                    play();
            }

            public void close() {
                    if (player != null) {
                            player.close();
                            player = null;
                    }
            }
    }


    使用方法

    // 创建播放声音对象
    LPAudioPlayer mid = new LPAudioPlayer("back.mid", "audio/midi", true);
    // 设置循环播放
    mid.setLoop();
    // 播放音乐
    mid.play();

    转]查询手机支持的所有声音、视频文件格式的小代码


    网上抓来的,也许有些朋友能用得到。

    import javax.microedition.lcdui.*;
    import javax.microedition.midlet.*;
    import javax.microedition.media.*;

    public class MediaInformationMIDlet extends MIDlet implements CommandListener {
    private Form mInformationForm;
    public void startApp() {
    if (mInformationForm == null) {
    mInformationForm =
    new Form("Content types and protocols");
    String[] contentTypes =
    Manager.getSupportedContentTypes(null);
    for (int i = 0; i < contentTypes.length; i++) {
    String[] protocols =
    Manager.getSupportedProtocols(contentTypes[i]);
    for (int j = 0; j < protocols.length; j++) {
    StringItem si = new StringItem(contentTypes[i] + ": ",
    protocols[j]);
    //si.setLayout(Item.LAYOUT_NEWLINE_AFTER);
    mInformationForm.append(si);
    }
    }
    Command exitCommand = new Command("Exit", Command.EXIT, 0);
    mInformationForm.addCommand(exitCommand);
    mInformationForm.setCommandListener(this);
    }
    Display.getDisplay(this).setCurrent(mInformationForm);
    }
    public void pauseApp() {}

    public void destroyApp(boolean unconditional) {}
    public void commandAction(Command c, Displayable s) {
    notifyDestroyed();
    }
    }


    基于J2ME的SVGT移动应用(二)

    使用SVG 不可避免的要涉及XML的解析和使用。JSR-172是J2ME下访问WEB服务的标准API,提供了一个标准的轻量级XML解析器。JSR-172实现 了JAXP1.2(Java API for XML Processing)的一个子集,支持SAX2.0。在JSR-172中使用SAX方式处理XML数据,相比DOM的处理方式更加节省内存,因此在同样 的硬件条件下,SAX能够处理更大的XML文档或数据。JSR-172中包括3个包,其中javax.xml.parsers 包括SAX解析器,工厂和异常类;org.xml.sax中包括核心SAX API;org.xml.sax.helpers中包括多种辅助类。
    此外 ,用户还可以使用KXML等XML解析器在J2ME应用程序中处理XML数据,尤其是在平台不支持JSR-172的时候。
    以下是使用SAX解析XML的具体实例,其中省略了一些代码。首先创建SAX处理器类。
    class BasicHandler extends DefaultHandler
    {
    private Stack tagStack = new Stack();
    public BasicHandler (){}
    public void startDocument() throws SAXException {}
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException  {
        if(qName.equals("AAA")) { /*数据处理*/}
        tagStack.push(qName);
      }
    public void characters(char[] ch, int start, int length) throws SAXException {
        String chars = new String(ch, start, length).trim();
        if(chars.length() > 0){
          String qName = (String)tagStack.peek();
          if (qName.equals("BBB")) { /*数据处理*/}
    }
    }
    public void endElement(String uri, String localName, String qName, Attributes attributes) throws SAXException  {
        tagStack.pop();
      }
      public void endDocument() throws SAXException   { }
    }
    之后装入一个XML文件并指定为此前定义的SAX处理器。
    try
    {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      SAXParser saxParser = factory.newSAXParser();
      FileConnection fc = (FileConnection) Connector.open("file:///root1/phones.xml");
      InputStream is = fc.openInputStream();
      InputSource inputSource = new InputSource(is);
      saxParser.parse(is,new BasicHandler(this));
    }
    catch(Exception ex) {}
         我们也可以从一个输入流中加载XML,例如从一个XML字符串:
          InputStream is = new ByteArrayInputStream(xmlString.getBytes(), 0, xmlString.length());
          InputSource inputSource = new InputSource(is);
          saxParser.parse(is,new BasicHandler(svgCanvas));
     
    一个简单的SVG MIDP应用
        现在我们可以将上面提到的技术组合起来,形成一个完整基于手机短信的网络监控应用,功能是根据短信数据显示当前的网络状态。类图如下:
     
    其中MySamplePushRegistry为一个MIDP应用,启动 后显示界面为一个SvgCanvas类对象,并在在50001端口启动SMS侦听。SvgCanvas为SVG窗口类,负责显示SVG内容,这些内容来自 一个定义好的SVG文件,这里为一个简单的网络图,包括一个PC机,一台打印机以及之间的网络连接。BasicHandler为SAX解析处理器, Status类为短信数据类。
    应用程序的基本流程为:MIDP启动后显示SVG文件,并启动在SMS特 定端口侦听;在接收到XML短信数据后,MIDP使用BasicHandler解析XML,生成状态对象并存入对象列表;在解析结束后,通知 SvgCanvas将根据状态对象更新显示界面,在故障情况下将相应部件颜色改为红色,正常情况则为绿色。
    应用程序在模拟器中运行的情况如下:
    1, 启动画面
     
    2, 发送XML数据短信
    3,PC正常,与打印机连接故障和打印机故障的情况显示
     
    结论
    Mobile SVG已开始在MMS上显露身手,但实际上除了MMS,Mobile SVG还有丰富的应用,其中包括:
    l         娱乐教育等,包括各种手机游戏和在线教程等。
    l         基于位置的服务,在地图上显示运动物体及相关链接,同时允许用户缩放地图、切换不同图层的可见性、选择特定的区域等。具体应用如汽车导航、汽车调度、电子导游、移动广告等。
    l         现场服务:包括技术制图,设备监控等,借助于Mobile SVG,就可以绘制出前后一致的、高品质的图像,可以看全景,也可以看局部细节。
    l         其它任何JPG、GIF或其它位图格式不能满足要求的无线应用场合,如要求提供内容丰富、可伸缩、互动的图形或动画的地方。
     
    对于下一代无线系统(3G)来 说,是否能够成功取决于用户的需求。对于无线用户来说,如果存在更加吸引他们的应用,他们就会更换现有的手机。经由像 Mobile SVG这样以用户为中心的技术增强的MMS,将会产生更多促使手机升级的充分的理由。所以,对于业界来说,其面对的挑战是实现和应用Mobile SVG或其它矢量应用,例如FlashLite等。总的来说,在实现Mobile SVG的过程中,需要运营商、终端制造商、内容提供商共同努力,才能使Mobile SVG的无限魅力在资源受限的移动设备上大放光彩。